forked from Benqi-fi/BENQI-Smart-Contracts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
JumpRateModel.sol
105 lines (90 loc) · 4.42 KB
/
JumpRateModel.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
pragma solidity 0.5.17;
import "./InterestRateModel.sol";
import "./SafeMath.sol";
/**
* @title Benqi's JumpRateModel Contract
* @author Benqi
*/
contract JumpRateModel is InterestRateModel {
using SafeMath for uint;
event NewInterestParams(uint baseRatePerTimestamp, uint multiplierPerTimestamp, uint jumpMultiplierPerTimestamp, uint kink);
/**
* @notice The approximate number of timestamps per year that is assumed by the interest rate model
*/
uint public constant timestampsPerYear = 31536000;
/**
* @notice The multiplier of utilization rate that gives the slope of the interest rate
*/
uint public multiplierPerTimestamp;
/**
* @notice The base interest rate which is the y-intercept when utilization rate is 0
*/
uint public baseRatePerTimestamp;
/**
* @notice The multiplierPerTimestamp after hitting a specified utilization point
*/
uint public jumpMultiplierPerTimestamp;
/**
* @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 1e18)
* @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18)
* @param jumpMultiplierPerYear The multiplierPerTimestamp after hitting a specified utilization point
* @param kink_ The utilization point at which the jump multiplier is applied
*/
constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) public {
baseRatePerTimestamp = baseRatePerYear.mul(1e18).div(timestampsPerYear).div(1e18);
multiplierPerTimestamp = multiplierPerYear.mul(1e18).div(timestampsPerYear).div(1e18);
jumpMultiplierPerTimestamp = jumpMultiplierPerYear.mul(1e18).div(timestampsPerYear).div(1e18);
kink = kink_;
emit NewInterestParams(baseRatePerTimestamp, multiplierPerTimestamp, jumpMultiplierPerTimestamp, 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, 1e18]
*/
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.mul(1e18).div(cash.add(borrows).sub(reserves));
}
/**
* @notice Calculates the current borrow rate per timestmp, 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 timestmp as a mantissa (scaled by 1e18)
*/
function getBorrowRate(uint cash, uint borrows, uint reserves) public view returns (uint) {
uint util = utilizationRate(cash, borrows, reserves);
if (util <= kink) {
return util.mul(multiplierPerTimestamp).div(1e18).add(baseRatePerTimestamp);
} else {
uint normalRate = kink.mul(multiplierPerTimestamp).div(1e18).add(baseRatePerTimestamp);
uint excessUtil = util.sub(kink);
return excessUtil.mul(jumpMultiplierPerTimestamp).div(1e18).add(normalRate);
}
}
/**
* @notice Calculates the current supply rate per timestmp
* @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 timestmp as a mantissa (scaled by 1e18)
*/
function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) public view returns (uint) {
uint oneMinusReserveFactor = uint(1e18).sub(reserveFactorMantissa);
uint borrowRate = getBorrowRate(cash, borrows, reserves);
uint rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18);
return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18);
}
}