Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
974 lines (882 sloc)
31.2 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: AGPL-3.0-or-later | |
/// DssProxyActions.sol | |
// Copyright (C) 2018-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 GemLike { | |
function approve(address, uint) external; | |
function transfer(address, uint) external; | |
function transferFrom(address, address, uint) external; | |
function deposit() external payable; | |
function withdraw(uint) external; | |
} | |
interface ManagerLike { | |
function cdpCan(address, uint, address) external view returns (uint); | |
function ilks(uint) external view returns (bytes32); | |
function owns(uint) external view returns (address); | |
function urns(uint) external view returns (address); | |
function vat() external view returns (address); | |
function open(bytes32, address) external returns (uint); | |
function give(uint, address) external; | |
function cdpAllow(uint, address, uint) external; | |
function urnAllow(address, uint) external; | |
function frob(uint, int, int) external; | |
function flux(uint, address, uint) external; | |
function move(uint, address, uint) external; | |
function exit(address, uint, address, uint) external; | |
function quit(uint, address) external; | |
function enter(address, uint) external; | |
function shift(uint, uint) external; | |
} | |
interface VatLike { | |
function can(address, address) external view returns (uint); | |
function ilks(bytes32) external view returns (uint, uint, uint, uint, uint); | |
function dai(address) external view returns (uint); | |
function urns(bytes32, address) external view returns (uint, uint); | |
function frob(bytes32, address, address, address, int, int) external; | |
function hope(address) external; | |
function move(address, address, uint) external; | |
} | |
interface GemJoinLike { | |
function dec() external returns (uint); | |
function gem() external returns (GemLike); | |
function join(address, uint) external payable; | |
function exit(address, uint) external; | |
} | |
interface GNTJoinLike { | |
function bags(address) external view returns (address); | |
function make(address) external returns (address); | |
} | |
interface DaiJoinLike { | |
function vat() external returns (VatLike); | |
function dai() external returns (GemLike); | |
function join(address, uint) external payable; | |
function exit(address, uint) external; | |
} | |
interface HopeLike { | |
function hope(address) external; | |
function nope(address) external; | |
} | |
interface EndLike { | |
function fix(bytes32) external view returns (uint); | |
function cash(bytes32, uint) external; | |
function free(bytes32) external; | |
function pack(uint) external; | |
function skim(bytes32, address) external; | |
} | |
interface JugLike { | |
function drip(bytes32) external returns (uint); | |
} | |
interface PotLike { | |
function pie(address) external view returns (uint); | |
function drip() external returns (uint); | |
function join(uint) external; | |
function exit(uint) external; | |
} | |
interface ProxyRegistryLike { | |
function proxies(address) external view returns (address); | |
function build(address) external returns (address); | |
} | |
interface ProxyLike { | |
function owner() external view returns (address); | |
} | |
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
// WARNING: These functions meant to be used as a a library for a DSProxy. Some are unsafe if you call them directly. | |
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
contract Common { | |
uint256 constant RAY = 10 ** 27; | |
// Internal functions | |
function mul(uint x, uint y) internal pure returns (uint z) { | |
require(y == 0 || (z = x * y) / y == x, "mul-overflow"); | |
} | |
// Public functions | |
function daiJoin_join(address apt, address urn, uint wad) public { | |
// Gets DAI from the user's wallet | |
DaiJoinLike(apt).dai().transferFrom(msg.sender, address(this), wad); | |
// Approves adapter to take the DAI amount | |
DaiJoinLike(apt).dai().approve(apt, wad); | |
// Joins DAI into the vat | |
DaiJoinLike(apt).join(urn, wad); | |
} | |
} | |
contract DssProxyActions is Common { | |
// Internal functions | |
function sub(uint x, uint y) internal pure returns (uint z) { | |
require((z = x - y) <= x, "sub-overflow"); | |
} | |
function toInt(uint x) internal pure returns (int y) { | |
y = int(x); | |
require(y >= 0, "int-overflow"); | |
} | |
function toRad(uint wad) internal pure returns (uint rad) { | |
rad = mul(wad, 10 ** 27); | |
} | |
function convertTo18(address gemJoin, uint256 amt) internal returns (uint256 wad) { | |
// For those collaterals that have less than 18 decimals precision we need to do the conversion before passing to frob function | |
// Adapters will automatically handle the difference of precision | |
wad = mul( | |
amt, | |
10 ** (18 - GemJoinLike(gemJoin).dec()) | |
); | |
} | |
function _getDrawDart( | |
address vat, | |
address jug, | |
address urn, | |
bytes32 ilk, | |
uint wad | |
) internal returns (int dart) { | |
// Updates stability fee rate | |
uint rate = JugLike(jug).drip(ilk); | |
// Gets DAI balance of the urn in the vat | |
uint dai = VatLike(vat).dai(urn); | |
// If there was already enough DAI in the vat balance, just exits it without adding more debt | |
if (dai < mul(wad, RAY)) { | |
// Calculates the needed dart so together with the existing dai in the vat is enough to exit wad amount of DAI tokens | |
dart = toInt(sub(mul(wad, RAY), dai) / rate); | |
// This is neeeded due lack of precision. It might need to sum an extra dart wei (for the given DAI wad amount) | |
dart = mul(uint(dart), rate) < mul(wad, RAY) ? dart + 1 : dart; | |
} | |
} | |
function _getWipeDart( | |
address vat, | |
uint dai, | |
address urn, | |
bytes32 ilk | |
) internal view returns (int dart) { | |
// Gets actual rate from the vat | |
(, uint rate,,,) = VatLike(vat).ilks(ilk); | |
// Gets actual art value of the urn | |
(, uint art) = VatLike(vat).urns(ilk, urn); | |
// Uses the whole dai balance in the vat to reduce the debt | |
dart = toInt(dai / rate); | |
// Checks the calculated dart is not higher than urn.art (total debt), otherwise uses its value | |
dart = uint(dart) <= art ? - dart : - toInt(art); | |
} | |
function _getWipeAllWad( | |
address vat, | |
address usr, | |
address urn, | |
bytes32 ilk | |
) internal view returns (uint wad) { | |
// Gets actual rate from the vat | |
(, uint rate,,,) = VatLike(vat).ilks(ilk); | |
// Gets actual art value of the urn | |
(, uint art) = VatLike(vat).urns(ilk, urn); | |
// Gets actual dai amount in the urn | |
uint dai = VatLike(vat).dai(usr); | |
uint rad = sub(mul(art, rate), dai); | |
wad = rad / RAY; | |
// If the rad precision has some dust, it will need to request for 1 extra wad wei | |
wad = mul(wad, RAY) < rad ? wad + 1 : wad; | |
} | |
// Public functions | |
function transfer(address gem, address dst, uint amt) public { | |
GemLike(gem).transfer(dst, amt); | |
} | |
function ethJoin_join(address apt, address urn) public payable { | |
// Wraps ETH in WETH | |
GemJoinLike(apt).gem().deposit.value(msg.value)(); | |
// Approves adapter to take the WETH amount | |
GemJoinLike(apt).gem().approve(address(apt), msg.value); | |
// Joins WETH collateral into the vat | |
GemJoinLike(apt).join(urn, msg.value); | |
} | |
function gemJoin_join(address apt, address urn, uint amt, bool transferFrom) public { | |
// Only executes for tokens that have approval/transferFrom implementation | |
if (transferFrom) { | |
// Gets token from the user's wallet | |
GemJoinLike(apt).gem().transferFrom(msg.sender, address(this), amt); | |
// Approves adapter to take the token amount | |
GemJoinLike(apt).gem().approve(apt, amt); | |
} | |
// Joins token collateral into the vat | |
GemJoinLike(apt).join(urn, amt); | |
} | |
function hope( | |
address obj, | |
address usr | |
) public { | |
HopeLike(obj).hope(usr); | |
} | |
function nope( | |
address obj, | |
address usr | |
) public { | |
HopeLike(obj).nope(usr); | |
} | |
function open( | |
address manager, | |
bytes32 ilk, | |
address usr | |
) public returns (uint cdp) { | |
cdp = ManagerLike(manager).open(ilk, usr); | |
} | |
function give( | |
address manager, | |
uint cdp, | |
address usr | |
) public { | |
ManagerLike(manager).give(cdp, usr); | |
} | |
function giveToProxy( | |
address proxyRegistry, | |
address manager, | |
uint cdp, | |
address dst | |
) public { | |
// Gets actual proxy address | |
address proxy = ProxyRegistryLike(proxyRegistry).proxies(dst); | |
// Checks if the proxy address already existed and dst address is still the owner | |
if (proxy == address(0) || ProxyLike(proxy).owner() != dst) { | |
uint csize; | |
assembly { | |
csize := extcodesize(dst) | |
} | |
// We want to avoid creating a proxy for a contract address that might not be able to handle proxies, then losing the CDP | |
require(csize == 0, "Dst-is-a-contract"); | |
// Creates the proxy for the dst address | |
proxy = ProxyRegistryLike(proxyRegistry).build(dst); | |
} | |
// Transfers CDP to the dst proxy | |
give(manager, cdp, proxy); | |
} | |
function cdpAllow( | |
address manager, | |
uint cdp, | |
address usr, | |
uint ok | |
) public { | |
ManagerLike(manager).cdpAllow(cdp, usr, ok); | |
} | |
function urnAllow( | |
address manager, | |
address usr, | |
uint ok | |
) public { | |
ManagerLike(manager).urnAllow(usr, ok); | |
} | |
function flux( | |
address manager, | |
uint cdp, | |
address dst, | |
uint wad | |
) public { | |
ManagerLike(manager).flux(cdp, dst, wad); | |
} | |
function move( | |
address manager, | |
uint cdp, | |
address dst, | |
uint rad | |
) public { | |
ManagerLike(manager).move(cdp, dst, rad); | |
} | |
function frob( | |
address manager, | |
uint cdp, | |
int dink, | |
int dart | |
) public { | |
ManagerLike(manager).frob(cdp, dink, dart); | |
} | |
function quit( | |
address manager, | |
uint cdp, | |
address dst | |
) public { | |
ManagerLike(manager).quit(cdp, dst); | |
} | |
function enter( | |
address manager, | |
address src, | |
uint cdp | |
) public { | |
ManagerLike(manager).enter(src, cdp); | |
} | |
function shift( | |
address manager, | |
uint cdpSrc, | |
uint cdpOrg | |
) public { | |
ManagerLike(manager).shift(cdpSrc, cdpOrg); | |
} | |
function makeGemBag( | |
address gemJoin | |
) public returns (address bag) { | |
bag = GNTJoinLike(gemJoin).make(address(this)); | |
} | |
function lockETH( | |
address manager, | |
address ethJoin, | |
uint cdp | |
) public payable { | |
// Receives ETH amount, converts it to WETH and joins it into the vat | |
ethJoin_join(ethJoin, address(this)); | |
// Locks WETH amount into the CDP | |
VatLike(ManagerLike(manager).vat()).frob( | |
ManagerLike(manager).ilks(cdp), | |
ManagerLike(manager).urns(cdp), | |
address(this), | |
address(this), | |
toInt(msg.value), | |
0 | |
); | |
} | |
function safeLockETH( | |
address manager, | |
address ethJoin, | |
uint cdp, | |
address owner | |
) public payable { | |
require(ManagerLike(manager).owns(cdp) == owner, "owner-missmatch"); | |
lockETH(manager, ethJoin, cdp); | |
} | |
function lockGem( | |
address manager, | |
address gemJoin, | |
uint cdp, | |
uint amt, | |
bool transferFrom | |
) public { | |
// Takes token amount from user's wallet and joins into the vat | |
gemJoin_join(gemJoin, address(this), amt, transferFrom); | |
// Locks token amount into the CDP | |
VatLike(ManagerLike(manager).vat()).frob( | |
ManagerLike(manager).ilks(cdp), | |
ManagerLike(manager).urns(cdp), | |
address(this), | |
address(this), | |
toInt(convertTo18(gemJoin, amt)), | |
0 | |
); | |
} | |
function safeLockGem( | |
address manager, | |
address gemJoin, | |
uint cdp, | |
uint amt, | |
bool transferFrom, | |
address owner | |
) public { | |
require(ManagerLike(manager).owns(cdp) == owner, "owner-missmatch"); | |
lockGem(manager, gemJoin, cdp, amt, transferFrom); | |
} | |
function freeETH( | |
address manager, | |
address ethJoin, | |
uint cdp, | |
uint wad | |
) public { | |
// Unlocks WETH amount from the CDP | |
frob(manager, cdp, -toInt(wad), 0); | |
// Moves the amount from the CDP urn to proxy's address | |
flux(manager, cdp, address(this), wad); | |
// Exits WETH amount to proxy address as a token | |
GemJoinLike(ethJoin).exit(address(this), wad); | |
// Converts WETH to ETH | |
GemJoinLike(ethJoin).gem().withdraw(wad); | |
// Sends ETH back to the user's wallet | |
msg.sender.transfer(wad); | |
} | |
function freeGem( | |
address manager, | |
address gemJoin, | |
uint cdp, | |
uint amt | |
) public { | |
uint wad = convertTo18(gemJoin, amt); | |
// Unlocks token amount from the CDP | |
frob(manager, cdp, -toInt(wad), 0); | |
// Moves the amount from the CDP urn to proxy's address | |
flux(manager, cdp, address(this), wad); | |
// Exits token amount to the user's wallet as a token | |
GemJoinLike(gemJoin).exit(msg.sender, amt); | |
} | |
function exitETH( | |
address manager, | |
address ethJoin, | |
uint cdp, | |
uint wad | |
) public { | |
// Moves the amount from the CDP urn to proxy's address | |
flux(manager, cdp, address(this), wad); | |
// Exits WETH amount to proxy address as a token | |
GemJoinLike(ethJoin).exit(address(this), wad); | |
// Converts WETH to ETH | |
GemJoinLike(ethJoin).gem().withdraw(wad); | |
// Sends ETH back to the user's wallet | |
msg.sender.transfer(wad); | |
} | |
function exitGem( | |
address manager, | |
address gemJoin, | |
uint cdp, | |
uint amt | |
) public { | |
// Moves the amount from the CDP urn to proxy's address | |
flux(manager, cdp, address(this), convertTo18(gemJoin, amt)); | |
// Exits token amount to the user's wallet as a token | |
GemJoinLike(gemJoin).exit(msg.sender, amt); | |
} | |
function draw( | |
address manager, | |
address jug, | |
address daiJoin, | |
uint cdp, | |
uint wad | |
) public { | |
address urn = ManagerLike(manager).urns(cdp); | |
address vat = ManagerLike(manager).vat(); | |
bytes32 ilk = ManagerLike(manager).ilks(cdp); | |
// Generates debt in the CDP | |
frob(manager, cdp, 0, _getDrawDart(vat, jug, urn, ilk, wad)); | |
// Moves the DAI amount (balance in the vat in rad) to proxy's address | |
move(manager, cdp, address(this), toRad(wad)); | |
// Allows adapter to access to proxy's DAI balance in the vat | |
if (VatLike(vat).can(address(this), address(daiJoin)) == 0) { | |
VatLike(vat).hope(daiJoin); | |
} | |
// Exits DAI to the user's wallet as a token | |
DaiJoinLike(daiJoin).exit(msg.sender, wad); | |
} | |
function wipe( | |
address manager, | |
address daiJoin, | |
uint cdp, | |
uint wad | |
) public { | |
address vat = ManagerLike(manager).vat(); | |
address urn = ManagerLike(manager).urns(cdp); | |
bytes32 ilk = ManagerLike(manager).ilks(cdp); | |
address own = ManagerLike(manager).owns(cdp); | |
if (own == address(this) || ManagerLike(manager).cdpCan(own, cdp, address(this)) == 1) { | |
// Joins DAI amount into the vat | |
daiJoin_join(daiJoin, urn, wad); | |
// Paybacks debt to the CDP | |
frob(manager, cdp, 0, _getWipeDart(vat, VatLike(vat).dai(urn), urn, ilk)); | |
} else { | |
// Joins DAI amount into the vat | |
daiJoin_join(daiJoin, address(this), wad); | |
// Paybacks debt to the CDP | |
VatLike(vat).frob( | |
ilk, | |
urn, | |
address(this), | |
address(this), | |
0, | |
_getWipeDart(vat, wad * RAY, urn, ilk) | |
); | |
} | |
} | |
function safeWipe( | |
address manager, | |
address daiJoin, | |
uint cdp, | |
uint wad, | |
address owner | |
) public { | |
require(ManagerLike(manager).owns(cdp) == owner, "owner-missmatch"); | |
wipe(manager, daiJoin, cdp, wad); | |
} | |
function wipeAll( | |
address manager, | |
address daiJoin, | |
uint cdp | |
) public { | |
address vat = ManagerLike(manager).vat(); | |
address urn = ManagerLike(manager).urns(cdp); | |
bytes32 ilk = ManagerLike(manager).ilks(cdp); | |
(, uint art) = VatLike(vat).urns(ilk, urn); | |
address own = ManagerLike(manager).owns(cdp); | |
if (own == address(this) || ManagerLike(manager).cdpCan(own, cdp, address(this)) == 1) { | |
// Joins DAI amount into the vat | |
daiJoin_join(daiJoin, urn, _getWipeAllWad(vat, urn, urn, ilk)); | |
// Paybacks debt to the CDP | |
frob(manager, cdp, 0, -int(art)); | |
} else { | |
// Joins DAI amount into the vat | |
daiJoin_join(daiJoin, address(this), _getWipeAllWad(vat, address(this), urn, ilk)); | |
// Paybacks debt to the CDP | |
VatLike(vat).frob( | |
ilk, | |
urn, | |
address(this), | |
address(this), | |
0, | |
-int(art) | |
); | |
} | |
} | |
function safeWipeAll( | |
address manager, | |
address daiJoin, | |
uint cdp, | |
address owner | |
) public { | |
require(ManagerLike(manager).owns(cdp) == owner, "owner-missmatch"); | |
wipeAll(manager, daiJoin, cdp); | |
} | |
function lockETHAndDraw( | |
address manager, | |
address jug, | |
address ethJoin, | |
address daiJoin, | |
uint cdp, | |
uint wadD | |
) public payable { | |
address urn = ManagerLike(manager).urns(cdp); | |
address vat = ManagerLike(manager).vat(); | |
bytes32 ilk = ManagerLike(manager).ilks(cdp); | |
// Receives ETH amount, converts it to WETH and joins it into the vat | |
ethJoin_join(ethJoin, urn); | |
// Locks WETH amount into the CDP and generates debt | |
frob(manager, cdp, toInt(msg.value), _getDrawDart(vat, jug, urn, ilk, wadD)); | |
// Moves the DAI amount (balance in the vat in rad) to proxy's address | |
move(manager, cdp, address(this), toRad(wadD)); | |
// Allows adapter to access to proxy's DAI balance in the vat | |
if (VatLike(vat).can(address(this), address(daiJoin)) == 0) { | |
VatLike(vat).hope(daiJoin); | |
} | |
// Exits DAI to the user's wallet as a token | |
DaiJoinLike(daiJoin).exit(msg.sender, wadD); | |
} | |
function openLockETHAndDraw( | |
address manager, | |
address jug, | |
address ethJoin, | |
address daiJoin, | |
bytes32 ilk, | |
uint wadD | |
) public payable returns (uint cdp) { | |
cdp = open(manager, ilk, address(this)); | |
lockETHAndDraw(manager, jug, ethJoin, daiJoin, cdp, wadD); | |
} | |
function lockGemAndDraw( | |
address manager, | |
address jug, | |
address gemJoin, | |
address daiJoin, | |
uint cdp, | |
uint amtC, | |
uint wadD, | |
bool transferFrom | |
) public { | |
address urn = ManagerLike(manager).urns(cdp); | |
address vat = ManagerLike(manager).vat(); | |
bytes32 ilk = ManagerLike(manager).ilks(cdp); | |
// Takes token amount from user's wallet and joins into the vat | |
gemJoin_join(gemJoin, urn, amtC, transferFrom); | |
// Locks token amount into the CDP and generates debt | |
frob(manager, cdp, toInt(convertTo18(gemJoin, amtC)), _getDrawDart(vat, jug, urn, ilk, wadD)); | |
// Moves the DAI amount (balance in the vat in rad) to proxy's address | |
move(manager, cdp, address(this), toRad(wadD)); | |
// Allows adapter to access to proxy's DAI balance in the vat | |
if (VatLike(vat).can(address(this), address(daiJoin)) == 0) { | |
VatLike(vat).hope(daiJoin); | |
} | |
// Exits DAI to the user's wallet as a token | |
DaiJoinLike(daiJoin).exit(msg.sender, wadD); | |
} | |
function openLockGemAndDraw( | |
address manager, | |
address jug, | |
address gemJoin, | |
address daiJoin, | |
bytes32 ilk, | |
uint amtC, | |
uint wadD, | |
bool transferFrom | |
) public returns (uint cdp) { | |
cdp = open(manager, ilk, address(this)); | |
lockGemAndDraw(manager, jug, gemJoin, daiJoin, cdp, amtC, wadD, transferFrom); | |
} | |
function openLockGNTAndDraw( | |
address manager, | |
address jug, | |
address gntJoin, | |
address daiJoin, | |
bytes32 ilk, | |
uint amtC, | |
uint wadD | |
) public returns (address bag, uint cdp) { | |
// Creates bag (if doesn't exist) to hold GNT | |
bag = GNTJoinLike(gntJoin).bags(address(this)); | |
if (bag == address(0)) { | |
bag = makeGemBag(gntJoin); | |
} | |
// Transfer funds to the funds which previously were sent to the proxy | |
GemLike(GemJoinLike(gntJoin).gem()).transfer(bag, amtC); | |
cdp = openLockGemAndDraw(manager, jug, gntJoin, daiJoin, ilk, amtC, wadD, false); | |
} | |
function wipeAndFreeETH( | |
address manager, | |
address ethJoin, | |
address daiJoin, | |
uint cdp, | |
uint wadC, | |
uint wadD | |
) public { | |
address urn = ManagerLike(manager).urns(cdp); | |
// Joins DAI amount into the vat | |
daiJoin_join(daiJoin, urn, wadD); | |
// Paybacks debt to the CDP and unlocks WETH amount from it | |
frob( | |
manager, | |
cdp, | |
-toInt(wadC), | |
_getWipeDart(ManagerLike(manager).vat(), VatLike(ManagerLike(manager).vat()).dai(urn), urn, ManagerLike(manager).ilks(cdp)) | |
); | |
// Moves the amount from the CDP urn to proxy's address | |
flux(manager, cdp, address(this), wadC); | |
// Exits WETH amount to proxy address as a token | |
GemJoinLike(ethJoin).exit(address(this), wadC); | |
// Converts WETH to ETH | |
GemJoinLike(ethJoin).gem().withdraw(wadC); | |
// Sends ETH back to the user's wallet | |
msg.sender.transfer(wadC); | |
} | |
function wipeAllAndFreeETH( | |
address manager, | |
address ethJoin, | |
address daiJoin, | |
uint cdp, | |
uint wadC | |
) public { | |
address vat = ManagerLike(manager).vat(); | |
address urn = ManagerLike(manager).urns(cdp); | |
bytes32 ilk = ManagerLike(manager).ilks(cdp); | |
(, uint art) = VatLike(vat).urns(ilk, urn); | |
// Joins DAI amount into the vat | |
daiJoin_join(daiJoin, urn, _getWipeAllWad(vat, urn, urn, ilk)); | |
// Paybacks debt to the CDP and unlocks WETH amount from it | |
frob( | |
manager, | |
cdp, | |
-toInt(wadC), | |
-int(art) | |
); | |
// Moves the amount from the CDP urn to proxy's address | |
flux(manager, cdp, address(this), wadC); | |
// Exits WETH amount to proxy address as a token | |
GemJoinLike(ethJoin).exit(address(this), wadC); | |
// Converts WETH to ETH | |
GemJoinLike(ethJoin).gem().withdraw(wadC); | |
// Sends ETH back to the user's wallet | |
msg.sender.transfer(wadC); | |
} | |
function wipeAndFreeGem( | |
address manager, | |
address gemJoin, | |
address daiJoin, | |
uint cdp, | |
uint amtC, | |
uint wadD | |
) public { | |
address urn = ManagerLike(manager).urns(cdp); | |
// Joins DAI amount into the vat | |
daiJoin_join(daiJoin, urn, wadD); | |
uint wadC = convertTo18(gemJoin, amtC); | |
// Paybacks debt to the CDP and unlocks token amount from it | |
frob( | |
manager, | |
cdp, | |
-toInt(wadC), | |
_getWipeDart(ManagerLike(manager).vat(), VatLike(ManagerLike(manager).vat()).dai(urn), urn, ManagerLike(manager).ilks(cdp)) | |
); | |
// Moves the amount from the CDP urn to proxy's address | |
flux(manager, cdp, address(this), wadC); | |
// Exits token amount to the user's wallet as a token | |
GemJoinLike(gemJoin).exit(msg.sender, amtC); | |
} | |
function wipeAllAndFreeGem( | |
address manager, | |
address gemJoin, | |
address daiJoin, | |
uint cdp, | |
uint amtC | |
) public { | |
address vat = ManagerLike(manager).vat(); | |
address urn = ManagerLike(manager).urns(cdp); | |
bytes32 ilk = ManagerLike(manager).ilks(cdp); | |
(, uint art) = VatLike(vat).urns(ilk, urn); | |
// Joins DAI amount into the vat | |
daiJoin_join(daiJoin, urn, _getWipeAllWad(vat, urn, urn, ilk)); | |
uint wadC = convertTo18(gemJoin, amtC); | |
// Paybacks debt to the CDP and unlocks token amount from it | |
frob( | |
manager, | |
cdp, | |
-toInt(wadC), | |
-int(art) | |
); | |
// Moves the amount from the CDP urn to proxy's address | |
flux(manager, cdp, address(this), wadC); | |
// Exits token amount to the user's wallet as a token | |
GemJoinLike(gemJoin).exit(msg.sender, amtC); | |
} | |
} | |
contract DssProxyActionsEnd is Common { | |
// Internal functions | |
function _free( | |
address manager, | |
address end, | |
uint cdp | |
) internal returns (uint ink) { | |
bytes32 ilk = ManagerLike(manager).ilks(cdp); | |
address urn = ManagerLike(manager).urns(cdp); | |
VatLike vat = VatLike(ManagerLike(manager).vat()); | |
uint art; | |
(ink, art) = vat.urns(ilk, urn); | |
// If CDP still has debt, it needs to be paid | |
if (art > 0) { | |
EndLike(end).skim(ilk, urn); | |
(ink,) = vat.urns(ilk, urn); | |
} | |
// Approves the manager to transfer the position to proxy's address in the vat | |
if (vat.can(address(this), address(manager)) == 0) { | |
vat.hope(manager); | |
} | |
// Transfers position from CDP to the proxy address | |
ManagerLike(manager).quit(cdp, address(this)); | |
// Frees the position and recovers the collateral in the vat registry | |
EndLike(end).free(ilk); | |
} | |
// Public functions | |
function freeETH( | |
address manager, | |
address ethJoin, | |
address end, | |
uint cdp | |
) public { | |
uint wad = _free(manager, end, cdp); | |
// Exits WETH amount to proxy address as a token | |
GemJoinLike(ethJoin).exit(address(this), wad); | |
// Converts WETH to ETH | |
GemJoinLike(ethJoin).gem().withdraw(wad); | |
// Sends ETH back to the user's wallet | |
msg.sender.transfer(wad); | |
} | |
function freeGem( | |
address manager, | |
address gemJoin, | |
address end, | |
uint cdp | |
) public { | |
uint amt = _free(manager, end, cdp) / 10 ** (18 - GemJoinLike(gemJoin).dec()); | |
// Exits token amount to the user's wallet as a token | |
GemJoinLike(gemJoin).exit(msg.sender, amt); | |
} | |
function pack( | |
address daiJoin, | |
address end, | |
uint wad | |
) public { | |
daiJoin_join(daiJoin, address(this), wad); | |
VatLike vat = DaiJoinLike(daiJoin).vat(); | |
// Approves the end to take out DAI from the proxy's balance in the vat | |
if (vat.can(address(this), address(end)) == 0) { | |
vat.hope(end); | |
} | |
EndLike(end).pack(wad); | |
} | |
function cashETH( | |
address ethJoin, | |
address end, | |
bytes32 ilk, | |
uint wad | |
) public { | |
EndLike(end).cash(ilk, wad); | |
uint wadC = mul(wad, EndLike(end).fix(ilk)) / RAY; | |
// Exits WETH amount to proxy address as a token | |
GemJoinLike(ethJoin).exit(address(this), wadC); | |
// Converts WETH to ETH | |
GemJoinLike(ethJoin).gem().withdraw(wadC); | |
// Sends ETH back to the user's wallet | |
msg.sender.transfer(wadC); | |
} | |
function cashGem( | |
address gemJoin, | |
address end, | |
bytes32 ilk, | |
uint wad | |
) public { | |
EndLike(end).cash(ilk, wad); | |
// Exits token amount to the user's wallet as a token | |
uint amt = mul(wad, EndLike(end).fix(ilk)) / RAY / 10 ** (18 - GemJoinLike(gemJoin).dec()); | |
GemJoinLike(gemJoin).exit(msg.sender, amt); | |
} | |
} | |
contract DssProxyActionsDsr is Common { | |
function join( | |
address daiJoin, | |
address pot, | |
uint wad | |
) public { | |
VatLike vat = DaiJoinLike(daiJoin).vat(); | |
// Executes drip to get the chi rate updated to rho == now, otherwise join will fail | |
uint chi = PotLike(pot).drip(); | |
// Joins wad amount to the vat balance | |
daiJoin_join(daiJoin, address(this), wad); | |
// Approves the pot to take out DAI from the proxy's balance in the vat | |
if (vat.can(address(this), address(pot)) == 0) { | |
vat.hope(pot); | |
} | |
// Joins the pie value (equivalent to the DAI wad amount) in the pot | |
PotLike(pot).join(mul(wad, RAY) / chi); | |
} | |
function exit( | |
address daiJoin, | |
address pot, | |
uint wad | |
) public { | |
VatLike vat = DaiJoinLike(daiJoin).vat(); | |
// Executes drip to count the savings accumulated until this moment | |
uint chi = PotLike(pot).drip(); | |
// Calculates the pie value in the pot equivalent to the DAI wad amount | |
uint pie = mul(wad, RAY) / chi; | |
// Exits DAI from the pot | |
PotLike(pot).exit(pie); | |
// Checks the actual balance of DAI in the vat after the pot exit | |
uint bal = DaiJoinLike(daiJoin).vat().dai(address(this)); | |
// Allows adapter to access to proxy's DAI balance in the vat | |
if (vat.can(address(this), address(daiJoin)) == 0) { | |
vat.hope(daiJoin); | |
} | |
// It is necessary to check if due rounding the exact wad amount can be exited by the adapter. | |
// Otherwise it will do the maximum DAI balance in the vat | |
DaiJoinLike(daiJoin).exit( | |
msg.sender, | |
bal >= mul(wad, RAY) ? wad : bal / RAY | |
); | |
} | |
function exitAll( | |
address daiJoin, | |
address pot | |
) public { | |
VatLike vat = DaiJoinLike(daiJoin).vat(); | |
// Executes drip to count the savings accumulated until this moment | |
uint chi = PotLike(pot).drip(); | |
// Gets the total pie belonging to the proxy address | |
uint pie = PotLike(pot).pie(address(this)); | |
// Exits DAI from the pot | |
PotLike(pot).exit(pie); | |
// Allows adapter to access to proxy's DAI balance in the vat | |
if (vat.can(address(this), address(daiJoin)) == 0) { | |
vat.hope(daiJoin); | |
} | |
// Exits the DAI amount corresponding to the value of pie | |
DaiJoinLike(daiJoin).exit(msg.sender, mul(chi, pie) / RAY); | |
} | |
} |