forked from Benqi-fi/BENQI-Smart-Contracts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWhitePaperInterestRateModel.sol
85 lines (73 loc) · 3.58 KB
/
WhitePaperInterestRateModel.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
pragma solidity 0.5.17;
import "./InterestRateModel.sol";
import "./SafeMath.sol";
/**
* @title Benqi's WhitePaperInterestRateModel Contract
* @author Benqi
* @notice The parameterized model described in section 2.4 of the original Benqi Protocol whitepaper
*/
contract WhitePaperInterestRateModel is InterestRateModel {
using SafeMath for uint;
event NewInterestParams(uint baseRatePerTimestamp, uint multiplierPerTimestamp);
/**
* @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 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)
*/
constructor(uint baseRatePerYear, uint multiplierPerYear) public {
baseRatePerTimestamp = baseRatePerYear.mul(1e18).div(timestampsPerYear).div(1e18);
multiplierPerTimestamp = multiplierPerYear.mul(1e18).div(timestampsPerYear).div(1e18);
emit NewInterestParams(baseRatePerTimestamp, multiplierPerTimestamp);
}
/**
* @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 ur = utilizationRate(cash, borrows, reserves);
return ur.mul(multiplierPerTimestamp).div(1e18).add(baseRatePerTimestamp);
}
/**
* @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);
}
}