-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
contracts: Add interfaces #80
Conversation
Regarding combined operations: could we keep those outside the core contracts, i.e. in zapper contracts using "on behalf of" functionality? Just a thought. Edit: I guess we should bake in at least a combined open Trove + delegate, as it could save some gas (to be seen). |
|
||
function claimCollateral() external; | ||
function delegateInterest(uint256 _troveId, address _delegate) external; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you undelegate? Is the idea to reuse adjustTroveInterestRate()
for that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking of delegating to zero address (or to owner), but that’s an option too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought of adjustTroveInterestRate()
because I expect many people to also change their interest rate at the time of undelegation, so this would save an operation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Upon further thought, there should probably be 2 different calls for interest rate delegation:
delegateInterestRateToIndividualManager(troveId, manager, min, max)
delegateInterestRateToBatchManager(troveId, batchManager)
The first one would grant the arbitrary address "manager
" the right to call adjustTroveInterestRate()
on the Trove with an interest rate within range of [min, max]
. The owner of the Trove can undelegate by passing a zero address (or their own address) to the same function, like you suggested.
The second form is for batch delegation (duh) and requires batchManager
address to have previously registered themselves as a batch manager, providing a [min, max]
range (as well as a management fee) which can't be changed later. Undelegation in this case involves removing the Trove from the batch and reinserting it into a new position in the list, most likely even if the owner continues to use the last interest rate set by the batch manager (because batches must be kept contiguous). As such, we could either reuse adjustTroveInterestRate()
for undelegation (and have it recognize when a Trove is part of a batch, and perform removal), or have a dedicated function that shares some of its internals with adjustTroveInterestRate()
. I tend to prefer the latter as I dislike functions that branch too much, so I would add one more function:
undelegateInterestRateFromBatchManager(troveId, newAnnualInterestRate, upperHint, lowerHint)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, we probably have to add hints to batch delegation too, as in:
delegateInterestRateToBatchManager(troveId, batchManager, upperHint, lowerHint)
Most of the time, hints won't be crucial as each batch will store "pointers" to both ends of its slice of the list for the purpose of quickly skipping over the entire batch, which can be used to find the correct insertion point on-chain. However, if a batch is empty, we don't know the correct position of constituents yet, so we need a hint.
Alternatively, we could put placeholder nodes in the list for each batch manager (or just empty batches) where new Troves are to be inserted, but this could be abused (spamming the list full of useless empty batches that make traversing the list costly, e.g. when redeeming). For that reason, I prefer hints.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, your reasoning above make a lot of sense to me. Feel free to add a commit with those new function signatures so they don’t get lost in this comments.
Thanks!
@@ -24,25 +24,29 @@ interface IBorrowerOperations is ILiquityBase { | |||
address _boldTokenAddress | |||
) external; | |||
|
|||
function openTrove(uint _maxFee, uint256 _ETHAmount, uint _boldAmount, address _upperHint, address _lowerHint, uint256 _annualInterestRate) external; | |||
function openTrove(address _owner, uint256 _ownerIndex, uint _maxFee, uint256 _ETHAmount, uint _boldAmount, address _upperHint, address _lowerHint, uint256 _annualInterestRate, uint256 _spDeposit) external; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know combined operations will be coming later, but there's one that's worth considering already: opening a Trove with a delegated interest rate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely! Good idea.
|
||
function adjustTrove(uint _maxFee, uint _collChange, bool _isCollIncrease, uint _debtChange, bool isDebtIncrease) external; | ||
function adjustTrove(uint256 _troveId, uint _maxFee, uint _collChange, bool _isCollIncrease, uint _debtChange, bool isDebtIncrease) external; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is _maxFee
still needed? I know there's still an upfront interest payment (1 week's worth), but it's no longer unpredictable, like the borrow fee in v1 (unless you're delegating I guess, which is not the case for normal openTrove()
/ adjustTrove()
/ withdrawBold()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I’ll remove it.
/* buyETHBatch(): | ||
* Swap ETH to Bold using opt-in swap facility liquidation gains, from multiple depositors | ||
*/ | ||
function buyETHBatch(address[] calldata _depositors, uint256 _ethAmount) external; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't thought this through, but shouldn't _ethAmount
also be an array (of how much to buy from each depositor)? Or is the idea to move on from one depositor to the next when its intent is fully used up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, my idea was the latter. I’m assuming you would order the array from most favorable to least.
Noticed there are no changes related to multi-collateral. I guess the idea is to have multiple instances of TroveManager/BorrowerOperations/StabilityPool etc., and redemption would be moved to its own contract as it interacts with every collateral type, right? Will each collateral have its own NFT contract for Troves, or do we want it to be shared? |
Yes, exactly.
Yes, that was my idea, to keep it simpler (in terms of backend code). If these NFTs were to be traded on OpenSea and the like, it would be confusing, but I don’t think that’s the case. We just care about |
|
||
function addColl(uint256 _ETHAmount) external; | ||
function addColl(uint256 _troveId, uint256 _ETHAmount) external; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does _ETHAMount
(and generally, the term ETH) represent WETH and LSTs in the contracts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, exactly. Technically it’s actually any ERC20 used as collateral, but in our case it will be WETH and some LSTs.
First draft of interfaces changes for the frontend.
I skipped: