// 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;
contract VatLike {
function hope(address) external;
}
contract 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;
}
contract JoinLike {
function dai() external view returns (address);
function join(address, uint256) external;
function exit(address, uint256) external;
}
contract 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);
}
}
{
"compilationTarget": {
"DsrManager.sol": "DsrManager"
},
"evmVersion": "petersburg",
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"pot_","type":"address"},{"internalType":"address","name":"daiJoin_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Exit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Join","type":"event"},{"constant":true,"inputs":[],"name":"dai","outputs":[{"internalType":"contract GemLike","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"}],"name":"daiBalance","outputs":[{"internalType":"uint256","name":"wad","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"daiJoin","outputs":[{"internalType":"contract JoinLike","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"exit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"dst","type":"address"}],"name":"exitAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"join","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pieOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pot","outputs":[{"internalType":"contract PotLike","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"supply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]