From a5fef173cd5440661d4612c83549e27ad90cb494 Mon Sep 17 00:00:00 2001 From: 0age <37939117+0age@users.noreply.github.com> Date: Fri, 24 Apr 2020 18:22:09 -0400 Subject: [PATCH] Modify DAIInterestRateModel.sol => DAIInterestRateModelV2.sol (#23) * Modify DAIInterestRateModel.sol => DAIInterestRateModelV2.sol The primary intention behind this change is to "smooth out" the cDai interest rate model to promote greater rate stability. It does so by increasing the `gapPerBlock`, or additional "slope" of the interest rate curve added to the Dai stability fee, from 0.05% to 2%. There are also a few minor changes, designed to clean up the interest rate model contract. Summary of changes: - `gapPerBlock` constant changed from `0.05e16 / blocksPerYear` to `2e16 / blocksPerYear` - `uint` => `uint256` (explicit > implicit) - added parenthesis to SafeMath expressions to make ordering explicit - used an interface (rather than an abstract contract) for the maker interfaces - modified a tiny bit of `poke()` to add `gapPerBlock` to `stabilityFeePerBlock` _before_ subtracting `baseRatePerBlock` for resiliency against a very unlikely underflow - named some unnamed return values * strip out stylistic changes from DAIInterestRateModelV2 * make changes to DAIInterestRateModelV2 as slim as possible --- ...teModel.sol => DAIInterestRateModelV2.sol} | 27 ++++++++++++------- tests/Models/DAIInterestRateModelTest.js | 10 +++---- 2 files changed, 23 insertions(+), 14 deletions(-) rename contracts/{DAIInterestRateModel.sol => DAIInterestRateModelV2.sol} (82%) diff --git a/contracts/DAIInterestRateModel.sol b/contracts/DAIInterestRateModelV2.sol similarity index 82% rename from contracts/DAIInterestRateModel.sol rename to contracts/DAIInterestRateModelV2.sol index 3efb79a55..d716b543e 100644 --- a/contracts/DAIInterestRateModel.sol +++ b/contracts/DAIInterestRateModelV2.sol @@ -4,17 +4,21 @@ import "./JumpRateModel.sol"; import "./SafeMath.sol"; /** - * @title Compound's DAIInterestRateModel Contract - * @author Compound - * @notice The parameterized model described in section 2.4 of the original Compound Protocol whitepaper + * @title Compound's DAIInterestRateModel Contract (version 2) + * @author Compound (modified by Dharma Labs) + * @notice The parameterized model described in section 2.4 of the original Compound Protocol whitepaper. + * Version 2 modifies the original interest rate model by increasing the "gap" or slope of the model prior + * to the "kink" from 0.05% to 2% with the goal of "smoothing out" interest rate changes as the utilization + * rate increases. */ -contract DAIInterestRateModel is JumpRateModel { +contract DAIInterestRateModelV2 is JumpRateModel { using SafeMath for uint; /** - * @notice The additional margin per block separating the base borrow rate from the roof (0.05% / block) + * @notice The additional margin per block separating the base borrow rate from the roof (2% / block). + * Note that this value has been increased from the original value of 0.05% per block. */ - uint public constant gapPerBlock = 0.05e16 / blocksPerYear; + uint public constant gapPerBlock = 2e16 / blocksPerYear; /** * @notice The assumed (1 - reserve factor) used to calculate the minimum borrow rate (reserve factor = 0.05) @@ -103,7 +107,12 @@ interface PotLike { } interface JugLike { - function ilks(bytes32) external view returns (uint duty, uint rho); - function base() external view returns (uint); -} + // --- Data --- + struct Ilk { + uint256 duty; + uint256 rho; + } + mapping (bytes32 => Ilk) public ilks; + uint256 public base; +} diff --git a/tests/Models/DAIInterestRateModelTest.js b/tests/Models/DAIInterestRateModelTest.js index 3dac04f8f..9906b76e7 100644 --- a/tests/Models/DAIInterestRateModelTest.js +++ b/tests/Models/DAIInterestRateModelTest.js @@ -18,7 +18,7 @@ function baseRoofRateFn(dsr, duty, mkrBase, jump, kink, cash, borrows, reserves) const assumedOneMinusReserveFactor = 0.95; const stabilityFeePerBlock = (duty + mkrBase - 1) * 15; const dsrPerBlock = (dsr - 1) * 15; - const gapPerBlock = 0.0005 / blocksPerYear; + const gapPerBlock = 0.02 / blocksPerYear; const jumpPerBlock = jump / blocksPerYear; let baseRatePerBlock = dsrPerBlock / assumedOneMinusReserveFactor, multiplierPerBlock; @@ -68,7 +68,7 @@ async function getKovanFork() { return {kovan, root, accounts}; } -describe('DAIInterestRateModel', () => { +describe('DAIInterestRateModelV2', () => { describe("constructor", () => { it.skip("sets jug and ilk address and pokes", async () => { // NB: Going back a certain distance requires an archive node, currently that add-on is $250/mo @@ -76,7 +76,7 @@ describe('DAIInterestRateModel', () => { const {kovan, root, accounts} = await getKovanFork(); // TODO: Get contract craz - let {contract: model} = await saddle.deployFull('DAIInterestRateModel', [ + let {contract: model} = await saddle.deployFull('DAIInterestRateModelV2', [ etherUnsigned(0.8e18), etherUnsigned(0.9e18), "0xea190dbdc7adf265260ec4da6e9675fd4f5a78bb", @@ -151,7 +151,7 @@ describe('DAIInterestRateModel', () => { etherUnsigned(perSecondBase) ]); - const daiIRM = await deploy('DAIInterestRateModel', [ + const daiIRM = await deploy('DAIInterestRateModelV2', [ etherUnsigned(jump), etherUnsigned(kink), pot._address, @@ -227,7 +227,7 @@ describe('DAIInterestRateModel', () => { etherUnsigned(perSecondBase) ]); - const daiIRM = await deploy('DAIInterestRateModel', [ + const daiIRM = await deploy('DAIInterestRateModelV2', [ etherUnsigned(jump), etherUnsigned(kink), pot._address,