File 1 of 1: DssPsm.sol
pragma solidity ^0.6.7;
pragma solidity >=0.5.12;
interface DaiJoinAbstract {
function wards(address) external view returns (uint256);
function rely(address usr) external;
function deny(address usr) external;
function vat() external view returns (address);
function dai() external view returns (address);
function live() external view returns (uint256);
function cage() external;
function join(address, uint256) external;
function exit(address, uint256) external;
}
pragma solidity >=0.5.12;
interface DaiAbstract {
function wards(address) external view returns (uint256);
function rely(address) external;
function deny(address) external;
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function version() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address) external view returns (uint256);
function allowance(address, address) external view returns (uint256);
function nonces(address) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external view returns (bytes32);
function transfer(address, uint256) external;
function transferFrom(address, address, uint256) external returns (bool);
function mint(address, uint256) external;
function burn(address, uint256) external;
function approve(address, uint256) external returns (bool);
function push(address, uint256) external;
function pull(address, uint256) external;
function move(address, address, uint256) external;
function permit(address, address, uint256, uint256, bool, uint8, bytes32, bytes32) external;
}
pragma solidity >=0.5.12;
interface VatAbstract {
function wards(address) external view returns (uint256);
function rely(address) external;
function deny(address) external;
function can(address, address) external view returns (uint256);
function hope(address) external;
function nope(address) external;
function ilks(bytes32) external view returns (uint256, uint256, uint256, uint256, uint256);
function urns(bytes32, address) external view returns (uint256, uint256);
function gem(bytes32, address) external view returns (uint256);
function dai(address) external view returns (uint256);
function sin(address) external view returns (uint256);
function debt() external view returns (uint256);
function vice() external view returns (uint256);
function Line() external view returns (uint256);
function live() external view returns (uint256);
function init(bytes32) external;
function file(bytes32, uint256) external;
function file(bytes32, bytes32, uint256) external;
function cage() external;
function slip(bytes32, address, int256) external;
function flux(bytes32, address, address, uint256) external;
function move(address, address, uint256) external;
function frob(bytes32, address, address, address, int256, int256) external;
function fork(bytes32, address, address, int256, int256) external;
function grab(bytes32, address, address, address, int256, int256) external;
function heal(uint256) external;
function suck(address, address, uint256) external;
function fold(bytes32, address, int256) external;
}
interface AuthGemJoinAbstract {
function dec() external view returns (uint256);
function vat() external view returns (address);
function ilk() external view returns (bytes32);
function join(address, uint256, address) external;
function exit(address, uint256) external;
}
contract DssPsm {
mapping (address => uint256) public wards;
function rely(address usr) external auth { wards[usr] = 1; emit Rely(usr); }
function deny(address usr) external auth { wards[usr] = 0; emit Deny(usr); }
modifier auth { require(wards[msg.sender] == 1); _; }
VatAbstract immutable public vat;
AuthGemJoinAbstract immutable public gemJoin;
DaiAbstract immutable public dai;
DaiJoinAbstract immutable public daiJoin;
bytes32 immutable public ilk;
address immutable public vow;
uint256 immutable internal to18ConversionFactor;
uint256 public tin;
uint256 public tout;
event Rely(address user);
event Deny(address user);
event File(bytes32 indexed what, uint256 data);
event SellGem(address indexed owner, uint256 value, uint256 fee);
event BuyGem(address indexed owner, uint256 value, uint256 fee);
constructor(address gemJoin_, address daiJoin_, address vow_) public {
wards[msg.sender] = 1;
emit Rely(msg.sender);
AuthGemJoinAbstract gemJoin__ = gemJoin = AuthGemJoinAbstract(gemJoin_);
DaiJoinAbstract daiJoin__ = daiJoin = DaiJoinAbstract(daiJoin_);
VatAbstract vat__ = vat = VatAbstract(address(gemJoin__.vat()));
DaiAbstract dai__ = dai = DaiAbstract(address(daiJoin__.dai()));
ilk = gemJoin__.ilk();
vow = vow_;
to18ConversionFactor = 10 ** (18 - gemJoin__.dec());
dai__.approve(daiJoin_, uint256(-1));
vat__.hope(daiJoin_);
}
uint256 constant WAD = 10 ** 18;
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 file(bytes32 what, uint256 data) external auth {
if (what == "tin") tin = data;
else if (what == "tout") tout = data;
else revert("DssPsm/file-unrecognized-param");
emit File(what, data);
}
function hope(address usr) external auth {
vat.hope(usr);
}
function nope(address usr) external auth {
vat.nope(usr);
}
function sellGem(address usr, uint256 gemAmt) external {
uint256 gemAmt18 = mul(gemAmt, to18ConversionFactor);
uint256 fee = mul(gemAmt18, tin) / WAD;
uint256 daiAmt = sub(gemAmt18, fee);
gemJoin.join(address(this), gemAmt, msg.sender);
vat.frob(ilk, address(this), address(this), address(this), int256(gemAmt18), int256(gemAmt18));
vat.move(address(this), vow, mul(fee, RAY));
daiJoin.exit(usr, daiAmt);
emit SellGem(usr, gemAmt, fee);
}
function buyGem(address usr, uint256 gemAmt) external {
uint256 gemAmt18 = mul(gemAmt, to18ConversionFactor);
uint256 fee = mul(gemAmt18, tout) / WAD;
uint256 daiAmt = add(gemAmt18, fee);
require(dai.transferFrom(msg.sender, address(this), daiAmt), "DssPsm/failed-transfer");
daiJoin.join(address(this), daiAmt);
vat.frob(ilk, address(this), address(this), address(this), -int256(gemAmt18), -int256(gemAmt18));
gemJoin.exit(usr, gemAmt);
vat.move(address(this), vow, mul(fee, RAY));
emit BuyGem(usr, gemAmt, fee);
}
}