-
Notifications
You must be signed in to change notification settings - Fork 15
/
DsrManager.sol
135 lines (112 loc) · 4.26 KB
/
DsrManager.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
// DsrManager.sol
// Copyright (C) 2020 Maker Ecosystem Growth Holdings, INC.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity >=0.5.12;
interface VatLike {
function hope(address) external;
}
interface PotLike {
function vat() external view returns (address);
function chi() external view returns (uint256);
function rho() external view returns (uint256);
function drip() external returns (uint256);
function join(uint256) external;
function exit(uint256) external;
}
interface JoinLike {
function dai() external view returns (address);
function join(address, uint256) external;
function exit(address, uint256) external;
}
interface GemLike {
function transferFrom(address,address,uint256) external returns (bool);
function approve(address,uint256) external returns (bool);
}
contract DsrManager {
PotLike public pot;
GemLike public dai;
JoinLike public daiJoin;
uint256 public supply;
mapping (address => uint256) public pieOf;
event Join(address indexed dst, uint256 wad);
event Exit(address indexed dst, uint256 wad);
uint256 constant RAY = 10 ** 27;
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x);
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x);
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(y == 0 || (z = x * y) / y == x);
}
function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
// always rounds down
z = mul(x, y) / RAY;
}
function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
// always rounds down
z = mul(x, RAY) / y;
}
function rdivup(uint256 x, uint256 y) internal pure returns (uint256 z) {
// always rounds up
z = add(mul(x, RAY), sub(y, 1)) / y;
}
constructor(address pot_, address daiJoin_) public {
pot = PotLike(pot_);
daiJoin = JoinLike(daiJoin_);
dai = GemLike(daiJoin.dai());
VatLike vat = VatLike(pot.vat());
vat.hope(address(daiJoin));
vat.hope(address(pot));
dai.approve(address(daiJoin), uint256(-1));
}
function daiBalance(address usr) external returns (uint256 wad) {
uint256 chi = (now > pot.rho()) ? pot.drip() : pot.chi();
wad = rmul(chi, pieOf[usr]);
}
// wad is denominated in dai
function join(address dst, uint256 wad) external {
uint256 chi = (now > pot.rho()) ? pot.drip() : pot.chi();
uint256 pie = rdiv(wad, chi);
pieOf[dst] = add(pieOf[dst], pie);
supply = add(supply, pie);
dai.transferFrom(msg.sender, address(this), wad);
daiJoin.join(address(this), wad);
pot.join(pie);
emit Join(dst, wad);
}
// wad is denominated in dai
function exit(address dst, uint256 wad) external {
uint256 chi = (now > pot.rho()) ? pot.drip() : pot.chi();
uint256 pie = rdivup(wad, chi);
require(pieOf[msg.sender] >= pie, "insufficient-balance");
pieOf[msg.sender] = sub(pieOf[msg.sender], pie);
supply = sub(supply, pie);
pot.exit(pie);
uint256 amt = rmul(chi, pie);
daiJoin.exit(dst, amt);
emit Exit(dst, amt);
}
function exitAll(address dst) external {
uint256 chi = (now > pot.rho()) ? pot.drip() : pot.chi();
uint256 pie = pieOf[msg.sender];
pieOf[msg.sender] = 0;
supply = sub(supply, pie);
pot.exit(pie);
uint256 amt = rmul(chi, pie);
daiJoin.exit(dst, amt);
emit Exit(dst, amt);
}
}