forked from compound-finance/compound-protocol
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update DAIInterestRateModel to v4 (compound-finance#230)
- Loading branch information
Showing
3 changed files
with
141 additions
and
8 deletions.
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,132 @@ | ||
pragma solidity ^0.8.10; | ||
|
||
import "./JumpRateModelV2.sol"; | ||
|
||
/** | ||
* @title Compound's DAIInterestRateModel Contract (version 4) | ||
* @author Compound, Dharma (modified by Maker Growth) | ||
* @notice The change from v3 to v4 of this contract was just the `SECONDS_PER_BLOCK` constant, | ||
* as noted in https://github.com/compound-finance/compound-protocol/issues/230 | ||
*/ | ||
contract DAIInterestRateModelV4 is JumpRateModelV2 { | ||
uint256 private constant BASE = 1e18; | ||
uint256 private constant RAY_BASE = 1e27; | ||
uint256 private constant RAY_TO_BASE_SCALE = 1e9; | ||
uint256 private constant SECONDS_PER_BLOCK = 12; | ||
|
||
/** | ||
* @notice The additional margin per block separating the base borrow rate from the roof. | ||
*/ | ||
uint public gapPerBlock; | ||
|
||
/** | ||
* @notice The assumed (1 - reserve factor) used to calculate the minimum borrow rate (reserve factor = 0.05) | ||
*/ | ||
uint public constant assumedOneMinusReserveFactorMantissa = 0.95e18; | ||
|
||
PotLike pot; | ||
JugLike jug; | ||
|
||
/** | ||
* @notice Construct an interest rate model | ||
* @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point | ||
* @param kink_ The utilization point at which the jump multiplier is applied | ||
* @param pot_ The address of the Dai pot (where DSR is earned) | ||
* @param jug_ The address of the Dai jug (where SF is kept) | ||
* @param owner_ The address of the owner, i.e. the Timelock contract (which has the ability to update parameters directly) | ||
*/ | ||
constructor(uint jumpMultiplierPerYear, uint kink_, address pot_, address jug_, address owner_) JumpRateModelV2(0, 0, jumpMultiplierPerYear, kink_, owner_) public { | ||
gapPerBlock = 4e16 / blocksPerYear; | ||
pot = PotLike(pot_); | ||
jug = JugLike(jug_); | ||
poke(); | ||
} | ||
|
||
/** | ||
* @notice External function to update the parameters of the interest rate model | ||
* @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by BASE). For DAI, this is calculated from DSR and SF. Input not used. | ||
* @param gapPerYear The Additional margin per year separating the base borrow rate from the roof. (scaled by BASE) | ||
* @param jumpMultiplierPerYear The jumpMultiplierPerYear after hitting a specified utilization point | ||
* @param kink_ The utilization point at which the jump multiplier is applied | ||
*/ | ||
function updateJumpRateModel(uint baseRatePerYear, uint gapPerYear, uint jumpMultiplierPerYear, uint kink_) override external { | ||
require(msg.sender == owner, "only the owner may call this function."); | ||
gapPerBlock = gapPerYear / blocksPerYear; | ||
updateJumpRateModelInternal(0, 0, jumpMultiplierPerYear, kink_); | ||
poke(); | ||
} | ||
|
||
/** | ||
* @notice Calculates the current supply interest rate per block including the Dai savings rate | ||
* @param cash The total amount of cash the market has | ||
* @param borrows The total amount of borrows the market has outstanding | ||
* @param reserves The total amnount of reserves the market has | ||
* @param reserveFactorMantissa The current reserve factor the market has | ||
* @return The supply rate per block (as a percentage, and scaled by BASE) | ||
*/ | ||
function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) override public view returns (uint) { | ||
uint protocolRate = super.getSupplyRate(cash, borrows, reserves, reserveFactorMantissa); | ||
|
||
uint underlying = cash + borrows - reserves; | ||
if (underlying == 0) { | ||
return protocolRate; | ||
} else { | ||
uint cashRate = cash * dsrPerBlock() / underlying; | ||
return cashRate + protocolRate; | ||
} | ||
} | ||
|
||
/** | ||
* @notice Calculates the Dai savings rate per block | ||
* @return The Dai savings rate per block (as a percentage, and scaled by BASE) | ||
*/ | ||
function dsrPerBlock() public view returns (uint) { | ||
return (pot.dsr() - RAY_BASE) // scaled RAY_BASE aka RAY, and includes an extra "ONE" before subtraction | ||
/ RAY_TO_BASE_SCALE // descale to BASE | ||
* SECONDS_PER_BLOCK; // seconds per block | ||
} | ||
|
||
/** | ||
* @notice Resets the baseRate and multiplier per block based on the stability fee and Dai savings rate | ||
*/ | ||
function poke() public { | ||
(uint duty, ) = jug.ilks("ETH-A"); | ||
uint stabilityFeePerBlock = (duty + jug.base() - RAY_BASE) / RAY_TO_BASE_SCALE * SECONDS_PER_BLOCK; | ||
|
||
// We ensure the minimum borrow rate >= DSR / (1 - reserve factor) | ||
baseRatePerBlock = dsrPerBlock() * BASE / assumedOneMinusReserveFactorMantissa; | ||
|
||
// The roof borrow rate is max(base rate, stability fee) + gap, from which we derive the slope | ||
if (baseRatePerBlock < stabilityFeePerBlock) { | ||
multiplierPerBlock = (stabilityFeePerBlock - baseRatePerBlock + gapPerBlock) * BASE / kink; | ||
} else { | ||
multiplierPerBlock = gapPerBlock * BASE / kink; | ||
} | ||
|
||
emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink); | ||
} | ||
} | ||
|
||
|
||
/*** Maker Interfaces ***/ | ||
|
||
interface PotLike { | ||
function chi() external view returns (uint); | ||
function dsr() external view returns (uint); | ||
function rho() external view returns (uint); | ||
function pie(address) external view returns (uint); | ||
function drip() external returns (uint); | ||
function join(uint) external; | ||
function exit(uint) external; | ||
} | ||
|
||
contract JugLike { | ||
// --- Data --- | ||
struct Ilk { | ||
uint256 duty; | ||
uint256 rho; | ||
} | ||
|
||
mapping (bytes32 => Ilk) public ilks; | ||
uint256 public base; | ||
} |
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