-
Notifications
You must be signed in to change notification settings - Fork 2
/
InterestRateModel.sol
151 lines (126 loc) · 5.08 KB
/
InterestRateModel.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
pragma solidity ^0.5.13;
import "./FixidityLib.sol";
import "./ExponentLib.sol";
import "./LogarithmLib.sol";
contract InterestRateModel {
using FixidityLib for FixidityLib.Fixidity;
using ExponentLib for FixidityLib.Fixidity;
using LogarithmLib for FixidityLib.Fixidity;
FixidityLib.Fixidity public fixidity;
address public admin;
int public constant point1 = 381966011250105152;//0.382*1e18, (3-sqrt(5))/2
int public constant point2 = 618033988749894848;//0.618*1e18, (sqrt(5)-1)/2
//https://www.mathsisfun.com/numbers/e-eulers-number.html
int public constant e = 2718281828459045235;//2.71828182845904523536*1e18
int public constant minInterest = 15000000000000000;//0.015*1e18
int public reserveRadio = 100000000000000000;//10% spread
constructor () public {
admin = msg.sender;
}
modifier onlyAdmin() {
require(msg.sender == admin, "only admin can do this!");
_;
}
function setAdmin(address newAdmin) public onlyAdmin {
admin = newAdmin;
}
function init(uint8 digits) public onlyAdmin {
fixidity.init(digits);
}
function setReserveRatio(int radio) public onlyAdmin {
reserveRadio = radio;
}
//y=0.015+x^e; x: [0, (3-sqrt(5))/2], [0,0.382]
function curve1(int x) public view returns (int y) {
// y = minInterest + x**e;
int xPowE = fixidity.power_any(x, e);//x**e
y = fixidity.add(minInterest, xPowE);
}
//y=0.015+((3-sqrt(5))/2)**(e-1)*x; x:[(3-sqrt(5))/2,(sqrt(5)-1)/2], [0.382,0.618]
function lineraSegment(int x) public view returns (int y) {
// require(x > point1 && x <= point2, "invalid x in lineraSegment");
int k = fixidity.power_any(point1, e-1e18);
int kx = fixidity.multiply(k, x);
y = fixidity.add(minInterest,kx);
}
// y = ((3-sqrt(5))/2)^(e-1) - (1-x)^e + 0.015
// y = 0.015 - (1-x)^e+point1^(e-1)
function curve2(int x) public view returns (int y) {
if (x == 1e18) {
y = 206337753576934987;//0.206337753576934987*1e18
} else {
int c = fixidity.power_any(point1, e-1e18);//point1^(e-1)
c = fixidity.add(c, minInterest);
int x2 = fixidity.power_any(fixidity.subtract(1e18, x), e);
y = fixidity.subtract(c, x2);
}
}
//获取使用率
function getBorrowPercent(int cash, int borrow) public view returns (int y) {
int total = fixidity.add(cash, borrow);
if (total == 0) {
y = 0;
} else {
y = fixidity.divide(borrow, total);
}
}
//loanRate
function getLoanRate(int cash, int borrow) public view returns (int y) {
int u = getBorrowPercent(cash, borrow);
if (u == 0) {
return minInterest;
}
if (fixidity.subtract(u, point1) < 0) {
y = curve1(u);
} else if (fixidity.subtract(u, point2) < 0) {
y = lineraSegment(u);
} else {
y = curve2(u);
}
}
//depositRate
function getDepositRate(int cash, int borrow) public view returns (int y) {
int loanRate = getLoanRate(cash, borrow);
int loanRatePercent = fixidity.multiply(loanRate, getBorrowPercent(cash, borrow));
y = fixidity.multiply(loanRatePercent, fixidity.subtract(1e18, reserveRadio));
}
//Index(a, n) = Index(a, n-1) * (1 + r*t), Index为本金
function calculateInterestIndex(int Index, int r, int t) public view returns (int y) {
if (t == 0) {
y = Index;
} else {
int rt = fixidity.multiply(r, t);
int sum = fixidity.add(rt, fixidity.fixed_1);
y = fixidity.multiply(Index, sum);//返回本息
}
}
//r为年利率,t为秒数,p*e^(rt)
function pert(int principal, int r, int t) public view returns (int y) {
if (t == 0 || r == 0) {
y = principal;
} else {
int r1 = fixidity.log_e(fixidity.add(r, fixidity.fixed_1));//r1 = ln(r+1)
int r2 = fixidity.divide(r1, 60*60*24*365*1e18);//r2=r1/(60*60*24*365)
int interest = fixidity.power_e(fixidity.multiply(r2, t*1e18));//e^(r2*t)
y = fixidity.multiply(principal, interest);//返回本息
}
}
function calculateBalance(int principal, int lastIndex, int newIndex) public view returns (int y) {
if (principal == 0 || lastIndex == 0) {
y = 0;
} else {
y = fixidity.divide(fixidity.multiply(principal, newIndex), lastIndex);
}
}
function mul(int a, int b) internal view returns (int c) {
c = fixidity.multiply(a, b);
}
function mul3(int a, int b, int c) internal view returns (int d) {
d = mul(a, mul(b, c));
}
function getNewReserve(int oldReserve, int cash, int borrow, int blockDelta) public view returns (int y) {
int borrowRate = getLoanRate(cash, borrow);
int simpleInterestFactor = fixidity.multiply(borrowRate, blockDelta);
y = fixidity.add(oldReserve, mul3(simpleInterestFactor, borrow, reserveRadio));
}
}