-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Update DAIInterestRateModel to v4 (fixes #230) #231
Open
fmorisan
wants to merge
8
commits into
compound-finance:master
Choose a base branch
from
fmorisan:dai-interest-model-v4
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
74e997e
Update DAIInterestRateModel to v4 (#230)
fmorisan 93f75af
chore: remove DAIInterestRateModelV3
fmorisan fc712b9
docs: change wording in DAI IRM v4 notice
fmorisan 9ee3aa3
fix: change DAI reserve factor to reflect current market conditions
fmorisan a4e8d65
fix: mul before div to avoid precision loss
fmorisan 1ab3f5d
docs: comment on reserve factor mantissa change
fmorisan 2ba1450
fix: syntax
fmorisan 2a6a050
feat: add BaseJumpRateModelV3 , fixing `blocksPerYear`
fmorisan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
pragma solidity ^0.8.10; | ||
|
||
import "./InterestRateModel.sol"; | ||
|
||
/** | ||
* @title Logic for Compound's JumpRateModel Contract V2. | ||
* @author Compound (modified by Dharma Labs, refactored by Arr00) | ||
* @notice Version 2 modifies Version 1 by enabling updateable parameters. | ||
*/ | ||
abstract contract BaseJumpRateModelV3 is InterestRateModel { | ||
event NewInterestParams(uint baseRatePerBlock, uint multiplierPerBlock, uint jumpMultiplierPerBlock, uint kink); | ||
|
||
uint256 private constant BASE = 1e18; | ||
|
||
/** | ||
* @notice The address of the owner, i.e. the Timelock contract, which can update parameters directly | ||
*/ | ||
address public owner; | ||
|
||
/** | ||
* @notice The approximate number of blocks per year that is assumed by the interest rate model | ||
* @dev This was calculated accounting for 12-second block times | ||
*/ | ||
uint public constant blocksPerYear = 2629800; | ||
|
||
/** | ||
* @notice The multiplier of utilization rate that gives the slope of the interest rate | ||
*/ | ||
uint public multiplierPerBlock; | ||
|
||
/** | ||
* @notice The base interest rate which is the y-intercept when utilization rate is 0 | ||
*/ | ||
uint public baseRatePerBlock; | ||
|
||
/** | ||
* @notice The multiplierPerBlock after hitting a specified utilization point | ||
*/ | ||
uint public jumpMultiplierPerBlock; | ||
|
||
/** | ||
* @notice The utilization point at which the jump multiplier is applied | ||
*/ | ||
uint public kink; | ||
|
||
/** | ||
* @notice Construct an interest rate model | ||
* @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by BASE) | ||
* @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by BASE) | ||
* @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point | ||
* @param kink_ The utilization point at which the jump multiplier is applied | ||
* @param owner_ The address of the owner, i.e. the Timelock contract (which has the ability to update parameters directly) | ||
*/ | ||
constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_, address owner_) internal { | ||
owner = owner_; | ||
|
||
updateJumpRateModelInternal(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_); | ||
} | ||
|
||
/** | ||
* @notice Update the parameters of the interest rate model (only callable by owner, i.e. Timelock) | ||
* @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by BASE) | ||
* @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by BASE) | ||
* @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point | ||
* @param kink_ The utilization point at which the jump multiplier is applied | ||
*/ | ||
function updateJumpRateModel(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) virtual external { | ||
require(msg.sender == owner, "only the owner may call this function."); | ||
|
||
updateJumpRateModelInternal(baseRatePerYear, multiplierPerYear, jumpMultiplierPerYear, kink_); | ||
} | ||
|
||
/** | ||
* @notice Calculates the utilization rate of the market: `borrows / (cash + borrows - reserves)` | ||
* @param cash The amount of cash in the market | ||
* @param borrows The amount of borrows in the market | ||
* @param reserves The amount of reserves in the market (currently unused) | ||
* @return The utilization rate as a mantissa between [0, BASE] | ||
*/ | ||
function utilizationRate(uint cash, uint borrows, uint reserves) public pure returns (uint) { | ||
// Utilization rate is 0 when there are no borrows | ||
if (borrows == 0) { | ||
return 0; | ||
} | ||
|
||
return borrows * BASE / (cash + borrows - reserves); | ||
} | ||
|
||
/** | ||
* @notice Calculates the current borrow rate per block, with the error code expected by the market | ||
* @param cash The amount of cash in the market | ||
* @param borrows The amount of borrows in the market | ||
* @param reserves The amount of reserves in the market | ||
* @return The borrow rate percentage per block as a mantissa (scaled by BASE) | ||
*/ | ||
function getBorrowRateInternal(uint cash, uint borrows, uint reserves) internal view returns (uint) { | ||
uint util = utilizationRate(cash, borrows, reserves); | ||
|
||
if (util <= kink) { | ||
return ((util * multiplierPerBlock) / BASE) + baseRatePerBlock; | ||
} else { | ||
uint normalRate = ((kink * multiplierPerBlock) / BASE) + baseRatePerBlock; | ||
uint excessUtil = util - kink; | ||
return ((excessUtil * jumpMultiplierPerBlock) / BASE) + normalRate; | ||
} | ||
} | ||
|
||
/** | ||
* @notice Calculates the current supply rate per block | ||
* @param cash The amount of cash in the market | ||
* @param borrows The amount of borrows in the market | ||
* @param reserves The amount of reserves in the market | ||
* @param reserveFactorMantissa The current reserve factor for the market | ||
* @return The supply rate percentage per block as a mantissa (scaled by BASE) | ||
*/ | ||
function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) virtual override public view returns (uint) { | ||
uint oneMinusReserveFactor = BASE - reserveFactorMantissa; | ||
uint borrowRate = getBorrowRateInternal(cash, borrows, reserves); | ||
uint rateToPool = borrowRate * oneMinusReserveFactor / BASE; | ||
return utilizationRate(cash, borrows, reserves) * rateToPool / BASE; | ||
} | ||
|
||
/** | ||
* @notice Internal function to update the parameters of the interest rate model | ||
* @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by BASE) | ||
* @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by BASE) | ||
* @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point | ||
* @param kink_ The utilization point at which the jump multiplier is applied | ||
*/ | ||
function updateJumpRateModelInternal(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) internal { | ||
baseRatePerBlock = baseRatePerYear / blocksPerYear; | ||
multiplierPerBlock = (multiplierPerYear * BASE) / (blocksPerYear * kink_); | ||
jumpMultiplierPerBlock = jumpMultiplierPerYear / blocksPerYear; | ||
kink = kink_; | ||
|
||
emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
pragma solidity ^0.8.10; | ||
|
||
import "./BaseJumpRateModelV3.sol"; | ||
import "./InterestRateModel.sol"; | ||
|
||
|
||
/** | ||
* @title Compound's JumpRateModel Contract V2 for V2 cTokens | ||
* @author Arr00 | ||
* @notice Supports only for V2 cTokens | ||
*/ | ||
contract JumpRateModelV2 is InterestRateModel, BaseJumpRateModelV3 { | ||
|
||
/** | ||
* @notice Calculates the current borrow rate per block | ||
* @param cash The amount of cash in the market | ||
* @param borrows The amount of borrows in the market | ||
* @param reserves The amount of reserves in the market | ||
* @return The borrow rate percentage per block as a mantissa (scaled by 1e18) | ||
*/ | ||
function getBorrowRate(uint cash, uint borrows, uint reserves) override external view returns (uint) { | ||
return getBorrowRateInternal(cash, borrows, reserves); | ||
} | ||
|
||
constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_, address owner_) | ||
|
||
BaseJumpRateModelV2(baseRatePerYear,multiplierPerYear,jumpMultiplierPerYear,kink_,owner_) public {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.