ETH Price: $2,070.87 (-2.31%)

Transaction Decoder

Block:
9909147 at Apr-20-2020 11:51:32 AM +UTC
Transaction Fee:
0.000613772 ETH $1.27
Gas Used:
153,443 Gas / 4 Gwei

Emitted Events:

160 0x0b5c54905a021b2c3c6dad0e8270a7dd0207cbab.0x1cff79cd00000000000000000000000000000000000000000000000000000000( 0x1cff79cd00000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000a1ed93bf44ba35f1e8ebfb4d104a0e109337a5aa, 0x00000000000000000000000007ee93aeea0a36fff2a9b95dd22bd6049ee54f26, 0x0000000000000000000000000000000000000000000000000000000000000040, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000004000000000, 000000000000000000000000000000000000000000000000000000c41cff79cd, 00000000000000000000000007ee93aeea0a36fff2a9b95dd22bd6049ee54f26, 0000000000000000000000000000000000000000000000000000000000000040, 0000000000000000000000000000000000000000000000000000000000000044, c77843b30000000000000000000000009759a6ac90977b93b58547b4a71c7831, 7f391a28000000000000000000000000197e90f9fad81970ba7976f33cbd7708, 8e5d7cf700000000000000000000000000000000000000000000000000000000 )
161 Vat.0xf24e23eb00000000000000000000000000000000000000000000000000000000( 0xf24e23eb00000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000a950524441892a31ebddf91d3ceefa04bf454466, 0x000000000000000000000000197e90f9fad81970ba7976f33cbd77088e5d7cf7, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, f24e23eb000000000000000000000000a950524441892a31ebddf91d3ceefa04, bf454466000000000000000000000000197e90f9fad81970ba7976f33cbd7708, 8e5d7cf700000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
162 Pot.0x9f678cca00000000000000000000000000000000000000000000000000000000( 0x9f678cca00000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000b5c54905a021b2c3c6dad0e8270a7dd0207cbab, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 9f678cca00000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
163 Vat.0xbb35783b00000000000000000000000000000000000000000000000000000000( 0xbb35783b00000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000197e90f9fad81970ba7976f33cbd77088e5d7cf7, 0x0000000000000000000000000b5c54905a021b2c3c6dad0e8270a7dd0207cbab, 0x0000000000000000000000033907dd34d26d24a6b08b5a86ff24e4355f63d902, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, bb35783b000000000000000000000000197e90f9fad81970ba7976f33cbd7708, 8e5d7cf70000000000000000000000000b5c54905a021b2c3c6dad0e8270a7dd, 0207cbab0000000000000000000000033907dd34d26d24a6b08b5a86ff24e435, 5f63d90200000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
164 Pot.0x7f8661a100000000000000000000000000000000000000000000000000000000( 0x7f8661a100000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000b5c54905a021b2c3c6dad0e8270a7dd0207cbab, 0x0000000000000000000000000000000000000000000000fad15b604f64b23fe6, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 7f8661a10000000000000000000000000000000000000000000000fad15b604f, 64b23fe600000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
165 Vat.0xbb35783b00000000000000000000000000000000000000000000000000000000( 0xbb35783b00000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000b5c54905a021b2c3c6dad0e8270a7dd0207cbab, 0x0000000000000000000000009759a6ac90977b93b58547b4a71c78317f391a28, 0x0000000000000000000000033907dd34d26d24a6af871ad78d9285fc38000000, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, bb35783b0000000000000000000000000b5c54905a021b2c3c6dad0e8270a7dd, 0207cbab0000000000000000000000009759a6ac90977b93b58547b4a71c7831, 7f391a280000000000000000000000033907dd34d26d24a6af871ad78d9285fc, 3800000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
166 Dai.Transfer( src=0x0000000000000000000000000000000000000000, dst=[Sender] 0xa1ed93bf44ba35f1e8ebfb4d104a0e109337a5aa, wad=4710092760935635903603 )
167 DaiJoin.0xef693bed00000000000000000000000000000000000000000000000000000000( 0xef693bed00000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000b5c54905a021b2c3c6dad0e8270a7dd0207cbab, 0x000000000000000000000000a1ed93bf44ba35f1e8ebfb4d104a0e109337a5aa, 0x0000000000000000000000000000000000000000000000ff55aafaee13746473, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, ef693bed000000000000000000000000a1ed93bf44ba35f1e8ebfb4d104a0e10, 9337a5aa0000000000000000000000000000000000000000000000ff55aafaee, 1374647300000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x197E90f9...88E5D7cf7
(Sky: MCD Pot)
0x35D1b3F3...259A0492B
(Sky: MCD Vat)
0x6B175474...495271d0F
0xA1eD93Bf...09337A5aa
81.342202476994933353 Eth
Nonce: 221
81.341588704994933353 Eth
Nonce: 222
0.000613772
(Ethermine)
884.945665755541194788 Eth884.946279527541194788 Eth0.000613772

Execution Trace

DSProxy #142,561.1cff79cd( )
  • DssProxyActionsDsr.exitAll( daiJoin=0x9759A6Ac90977b93B58547b4A71c78317f391A28, pot=0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7 )
    • DaiJoin.CALL( )
    • Pot.CALL( )
      • Vat.suck( u=0xA950524441892A31ebddF91d3cEEFa04Bf454466, v=0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7, rad=0 )
      • Pot.pie( 0x0b5C54905A021b2C3c6DaD0E8270A7Dd0207CBAB ) => ( 4626771775698303598566 )
      • Pot.exit( wad=4626771775698303598566 )
        • Vat.move( src=0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7, dst=0x0b5C54905A021b2C3c6DaD0E8270A7Dd0207CBAB, rad=4710092760935635903603314621458552144344696215810 )
        • Vat.can( 0x0b5C54905A021b2C3c6DaD0E8270A7Dd0207CBAB, 0x9759A6Ac90977b93B58547b4A71c78317f391A28 ) => ( 1 )
        • DaiJoin.exit( usr=0xA1eD93Bf44Ba35f1e8EBfB4d104A0e109337A5aa, wad=4710092760935635903603 )
          • Vat.move( src=0x0b5C54905A021b2C3c6DaD0E8270A7Dd0207CBAB, dst=0x9759A6Ac90977b93B58547b4A71c78317f391A28, rad=4710092760935635903603000000000000000000000000000 )
          • Dai.mint( usr=0xA1eD93Bf44Ba35f1e8EBfB4d104A0e109337A5aa, wad=4710092760935635903603 )
            File 1 of 5: Vat
            // hevm: flattened sources of /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/vat.sol
            pragma solidity =0.5.12;
            
            ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/vat.sol
            /// vat.sol -- Dai CDP database
            
            // Copyright (C) 2018 Rain <rainbreak@riseup.net>
            //
            // 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 Vat {
                // --- Auth ---
                mapping (address => uint) public wards;
                function rely(address usr) external note auth { require(live == 1, "Vat/not-live"); wards[usr] = 1; }
                function deny(address usr) external note auth { require(live == 1, "Vat/not-live"); wards[usr] = 0; }
                modifier auth {
                    require(wards[msg.sender] == 1, "Vat/not-authorized");
                    _;
                }
            
                mapping(address => mapping (address => uint)) public can;
                function hope(address usr) external note { can[msg.sender][usr] = 1; }
                function nope(address usr) external note { can[msg.sender][usr] = 0; }
                function wish(address bit, address usr) internal view returns (bool) {
                    return either(bit == usr, can[bit][usr] == 1);
                }
            
                // --- Data ---
                struct Ilk {
                    uint256 Art;   // Total Normalised Debt     [wad]
                    uint256 rate;  // Accumulated Rates         [ray]
                    uint256 spot;  // Price with Safety Margin  [ray]
                    uint256 line;  // Debt Ceiling              [rad]
                    uint256 dust;  // Urn Debt Floor            [rad]
                }
                struct Urn {
                    uint256 ink;   // Locked Collateral  [wad]
                    uint256 art;   // Normalised Debt    [wad]
                }
            
                mapping (bytes32 => Ilk)                       public ilks;
                mapping (bytes32 => mapping (address => Urn )) public urns;
                mapping (bytes32 => mapping (address => uint)) public gem;  // [wad]
                mapping (address => uint256)                   public dai;  // [rad]
                mapping (address => uint256)                   public sin;  // [rad]
            
                uint256 public debt;  // Total Dai Issued    [rad]
                uint256 public vice;  // Total Unbacked Dai  [rad]
                uint256 public Line;  // Total Debt Ceiling  [rad]
                uint256 public live;  // Access Flag
            
                // --- Logs ---
                event LogNote(
                    bytes4   indexed  sig,
                    bytes32  indexed  arg1,
                    bytes32  indexed  arg2,
                    bytes32  indexed  arg3,
                    bytes             data
                ) anonymous;
            
                modifier note {
                    _;
                    assembly {
                        // log an 'anonymous' event with a constant 6 words of calldata
                        // and four indexed topics: the selector and the first three args
                        let mark := msize                         // end of memory ensures zero
                        mstore(0x40, add(mark, 288))              // update free memory pointer
                        mstore(mark, 0x20)                        // bytes type data offset
                        mstore(add(mark, 0x20), 224)              // bytes size (padded)
                        calldatacopy(add(mark, 0x40), 0, 224)     // bytes payload
                        log4(mark, 288,                           // calldata
                             shl(224, shr(224, calldataload(0))), // msg.sig
                             calldataload(4),                     // arg1
                             calldataload(36),                    // arg2
                             calldataload(68)                     // arg3
                            )
                    }
                }
            
                // --- Init ---
                constructor() public {
                    wards[msg.sender] = 1;
                    live = 1;
                }
            
                // --- Math ---
                function add(uint x, int y) internal pure returns (uint z) {
                    z = x + uint(y);
                    require(y >= 0 || z <= x);
                    require(y <= 0 || z >= x);
                }
                function sub(uint x, int y) internal pure returns (uint z) {
                    z = x - uint(y);
                    require(y <= 0 || z <= x);
                    require(y >= 0 || z >= x);
                }
                function mul(uint x, int y) internal pure returns (int z) {
                    z = int(x) * y;
                    require(int(x) >= 0);
                    require(y == 0 || z / y == int(x));
                }
                function add(uint x, uint y) internal pure returns (uint z) {
                    require((z = x + y) >= x);
                }
                function sub(uint x, uint y) internal pure returns (uint z) {
                    require((z = x - y) <= x);
                }
                function mul(uint x, uint y) internal pure returns (uint z) {
                    require(y == 0 || (z = x * y) / y == x);
                }
            
                // --- Administration ---
                function init(bytes32 ilk) external note auth {
                    require(ilks[ilk].rate == 0, "Vat/ilk-already-init");
                    ilks[ilk].rate = 10 ** 27;
                }
                function file(bytes32 what, uint data) external note auth {
                    require(live == 1, "Vat/not-live");
                    if (what == "Line") Line = data;
                    else revert("Vat/file-unrecognized-param");
                }
                function file(bytes32 ilk, bytes32 what, uint data) external note auth {
                    require(live == 1, "Vat/not-live");
                    if (what == "spot") ilks[ilk].spot = data;
                    else if (what == "line") ilks[ilk].line = data;
                    else if (what == "dust") ilks[ilk].dust = data;
                    else revert("Vat/file-unrecognized-param");
                }
                function cage() external note auth {
                    live = 0;
                }
            
                // --- Fungibility ---
                function slip(bytes32 ilk, address usr, int256 wad) external note auth {
                    gem[ilk][usr] = add(gem[ilk][usr], wad);
                }
                function flux(bytes32 ilk, address src, address dst, uint256 wad) external note {
                    require(wish(src, msg.sender), "Vat/not-allowed");
                    gem[ilk][src] = sub(gem[ilk][src], wad);
                    gem[ilk][dst] = add(gem[ilk][dst], wad);
                }
                function move(address src, address dst, uint256 rad) external note {
                    require(wish(src, msg.sender), "Vat/not-allowed");
                    dai[src] = sub(dai[src], rad);
                    dai[dst] = add(dai[dst], rad);
                }
            
                function either(bool x, bool y) internal pure returns (bool z) {
                    assembly{ z := or(x, y)}
                }
                function both(bool x, bool y) internal pure returns (bool z) {
                    assembly{ z := and(x, y)}
                }
            
                // --- CDP Manipulation ---
                function frob(bytes32 i, address u, address v, address w, int dink, int dart) external note {
                    // system is live
                    require(live == 1, "Vat/not-live");
            
                    Urn memory urn = urns[i][u];
                    Ilk memory ilk = ilks[i];
                    // ilk has been initialised
                    require(ilk.rate != 0, "Vat/ilk-not-init");
            
                    urn.ink = add(urn.ink, dink);
                    urn.art = add(urn.art, dart);
                    ilk.Art = add(ilk.Art, dart);
            
                    int dtab = mul(ilk.rate, dart);
                    uint tab = mul(ilk.rate, urn.art);
                    debt     = add(debt, dtab);
            
                    // either debt has decreased, or debt ceilings are not exceeded
                    require(either(dart <= 0, both(mul(ilk.Art, ilk.rate) <= ilk.line, debt <= Line)), "Vat/ceiling-exceeded");
                    // urn is either less risky than before, or it is safe
                    require(either(both(dart <= 0, dink >= 0), tab <= mul(urn.ink, ilk.spot)), "Vat/not-safe");
            
                    // urn is either more safe, or the owner consents
                    require(either(both(dart <= 0, dink >= 0), wish(u, msg.sender)), "Vat/not-allowed-u");
                    // collateral src consents
                    require(either(dink <= 0, wish(v, msg.sender)), "Vat/not-allowed-v");
                    // debt dst consents
                    require(either(dart >= 0, wish(w, msg.sender)), "Vat/not-allowed-w");
            
                    // urn has no debt, or a non-dusty amount
                    require(either(urn.art == 0, tab >= ilk.dust), "Vat/dust");
            
                    gem[i][v] = sub(gem[i][v], dink);
                    dai[w]    = add(dai[w],    dtab);
            
                    urns[i][u] = urn;
                    ilks[i]    = ilk;
                }
                // --- CDP Fungibility ---
                function fork(bytes32 ilk, address src, address dst, int dink, int dart) external note {
                    Urn storage u = urns[ilk][src];
                    Urn storage v = urns[ilk][dst];
                    Ilk storage i = ilks[ilk];
            
                    u.ink = sub(u.ink, dink);
                    u.art = sub(u.art, dart);
                    v.ink = add(v.ink, dink);
                    v.art = add(v.art, dart);
            
                    uint utab = mul(u.art, i.rate);
                    uint vtab = mul(v.art, i.rate);
            
                    // both sides consent
                    require(both(wish(src, msg.sender), wish(dst, msg.sender)), "Vat/not-allowed");
            
                    // both sides safe
                    require(utab <= mul(u.ink, i.spot), "Vat/not-safe-src");
                    require(vtab <= mul(v.ink, i.spot), "Vat/not-safe-dst");
            
                    // both sides non-dusty
                    require(either(utab >= i.dust, u.art == 0), "Vat/dust-src");
                    require(either(vtab >= i.dust, v.art == 0), "Vat/dust-dst");
                }
                // --- CDP Confiscation ---
                function grab(bytes32 i, address u, address v, address w, int dink, int dart) external note auth {
                    Urn storage urn = urns[i][u];
                    Ilk storage ilk = ilks[i];
            
                    urn.ink = add(urn.ink, dink);
                    urn.art = add(urn.art, dart);
                    ilk.Art = add(ilk.Art, dart);
            
                    int dtab = mul(ilk.rate, dart);
            
                    gem[i][v] = sub(gem[i][v], dink);
                    sin[w]    = sub(sin[w],    dtab);
                    vice      = sub(vice,      dtab);
                }
            
                // --- Settlement ---
                function heal(uint rad) external note {
                    address u = msg.sender;
                    sin[u] = sub(sin[u], rad);
                    dai[u] = sub(dai[u], rad);
                    vice   = sub(vice,   rad);
                    debt   = sub(debt,   rad);
                }
                function suck(address u, address v, uint rad) external note auth {
                    sin[u] = add(sin[u], rad);
                    dai[v] = add(dai[v], rad);
                    vice   = add(vice,   rad);
                    debt   = add(debt,   rad);
                }
            
                // --- Rates ---
                function fold(bytes32 i, address u, int rate) external note auth {
                    require(live == 1, "Vat/not-live");
                    Ilk storage ilk = ilks[i];
                    ilk.rate = add(ilk.rate, rate);
                    int rad  = mul(ilk.Art, rate);
                    dai[u]   = add(dai[u], rad);
                    debt     = add(debt,   rad);
                }
            }

            File 2 of 5: Pot
            // hevm: flattened sources of /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/pot.sol
            pragma solidity =0.5.12;
            
            ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/lib.sol
            // This program is free software: you can redistribute it and/or modify
            // it under the terms of the GNU 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 General Public License for more details.
            
            // You should have received a copy of the GNU General Public License
            // along with this program.  If not, see <http://www.gnu.org/licenses/>.
            
            /* pragma solidity 0.5.12; */
            
            contract LibNote {
                event LogNote(
                    bytes4   indexed  sig,
                    address  indexed  usr,
                    bytes32  indexed  arg1,
                    bytes32  indexed  arg2,
                    bytes             data
                ) anonymous;
            
                modifier note {
                    _;
                    assembly {
                        // log an 'anonymous' event with a constant 6 words of calldata
                        // and four indexed topics: selector, caller, arg1 and arg2
                        let mark := msize                         // end of memory ensures zero
                        mstore(0x40, add(mark, 288))              // update free memory pointer
                        mstore(mark, 0x20)                        // bytes type data offset
                        mstore(add(mark, 0x20), 224)              // bytes size (padded)
                        calldatacopy(add(mark, 0x40), 0, 224)     // bytes payload
                        log4(mark, 288,                           // calldata
                             shl(224, shr(224, calldataload(0))), // msg.sig
                             caller,                              // msg.sender
                             calldataload(4),                     // arg1
                             calldataload(36)                     // arg2
                            )
                    }
                }
            }
            
            ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/pot.sol
            /// pot.sol -- Dai Savings Rate
            
            // Copyright (C) 2018 Rain <rainbreak@riseup.net>
            //
            // 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; */
            
            /* import "./lib.sol"; */
            
            /*
               "Savings Dai" is obtained when Dai is deposited into
               this contract. Each "Savings Dai" accrues Dai interest
               at the "Dai Savings Rate".
            
               This contract does not implement a user tradeable token
               and is intended to be used with adapters.
            
                     --- `save` your `dai` in the `pot` ---
            
               - `dsr`: the Dai Savings Rate
               - `pie`: user balance of Savings Dai
            
               - `join`: start saving some dai
               - `exit`: remove some dai
               - `drip`: perform rate collection
            
            */
            
            contract VatLike {
                function move(address,address,uint256) external;
                function suck(address,address,uint256) external;
            }
            
            contract Pot is LibNote {
                // --- Auth ---
                mapping (address => uint) public wards;
                function rely(address guy) external note auth { wards[guy] = 1; }
                function deny(address guy) external note auth { wards[guy] = 0; }
                modifier auth {
                    require(wards[msg.sender] == 1, "Pot/not-authorized");
                    _;
                }
            
                // --- Data ---
                mapping (address => uint256) public pie;  // user Savings Dai
            
                uint256 public Pie;  // total Savings Dai
                uint256 public dsr;  // the Dai Savings Rate
                uint256 public chi;  // the Rate Accumulator
            
                VatLike public vat;  // CDP engine
                address public vow;  // debt engine
                uint256 public rho;  // time of last drip
            
                uint256 public live;  // Access Flag
            
                // --- Init ---
                constructor(address vat_) public {
                    wards[msg.sender] = 1;
                    vat = VatLike(vat_);
                    dsr = ONE;
                    chi = ONE;
                    rho = now;
                    live = 1;
                }
            
                // --- Math ---
                uint256 constant ONE = 10 ** 27;
                function rpow(uint x, uint n, uint base) internal pure returns (uint z) {
                    assembly {
                        switch x case 0 {switch n case 0 {z := base} default {z := 0}}
                        default {
                            switch mod(n, 2) case 0 { z := base } default { z := x }
                            let half := div(base, 2)  // for rounding.
                            for { n := div(n, 2) } n { n := div(n,2) } {
                                let xx := mul(x, x)
                                if iszero(eq(div(xx, x), x)) { revert(0,0) }
                                let xxRound := add(xx, half)
                                if lt(xxRound, xx) { revert(0,0) }
                                x := div(xxRound, base)
                                if mod(n,2) {
                                    let zx := mul(z, x)
                                    if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0,0) }
                                    let zxRound := add(zx, half)
                                    if lt(zxRound, zx) { revert(0,0) }
                                    z := div(zxRound, base)
                                }
                            }
                        }
                    }
                }
            
                function rmul(uint x, uint y) internal pure returns (uint z) {
                    z = mul(x, y) / ONE;
                }
            
                function add(uint x, uint y) internal pure returns (uint z) {
                    require((z = x + y) >= x);
                }
            
                function sub(uint x, uint y) internal pure returns (uint z) {
                    require((z = x - y) <= x);
                }
            
                function mul(uint x, uint y) internal pure returns (uint z) {
                    require(y == 0 || (z = x * y) / y == x);
                }
            
                // --- Administration ---
                function file(bytes32 what, uint256 data) external note auth {
                    require(live == 1, "Pot/not-live");
                    require(now == rho, "Pot/rho-not-updated");
                    if (what == "dsr") dsr = data;
                    else revert("Pot/file-unrecognized-param");
                }
            
                function file(bytes32 what, address addr) external note auth {
                    if (what == "vow") vow = addr;
                    else revert("Pot/file-unrecognized-param");
                }
            
                function cage() external note auth {
                    live = 0;
                    dsr = ONE;
                }
            
                // --- Savings Rate Accumulation ---
                function drip() external note returns (uint tmp) {
                    require(now >= rho, "Pot/invalid-now");
                    tmp = rmul(rpow(dsr, now - rho, ONE), chi);
                    uint chi_ = sub(tmp, chi);
                    chi = tmp;
                    rho = now;
                    vat.suck(address(vow), address(this), mul(Pie, chi_));
                }
            
                // --- Savings Dai Management ---
                function join(uint wad) external note {
                    require(now == rho, "Pot/rho-not-updated");
                    pie[msg.sender] = add(pie[msg.sender], wad);
                    Pie             = add(Pie,             wad);
                    vat.move(msg.sender, address(this), mul(chi, wad));
                }
            
                function exit(uint wad) external note {
                    pie[msg.sender] = sub(pie[msg.sender], wad);
                    Pie             = sub(Pie,             wad);
                    vat.move(address(this), msg.sender, mul(chi, wad));
                }
            }

            File 3 of 5: Dai
            // hevm: flattened sources of /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/dai.sol
            pragma solidity =0.5.12;
            
            ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/lib.sol
            // This program is free software: you can redistribute it and/or modify
            // it under the terms of the GNU 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 General Public License for more details.
            
            // You should have received a copy of the GNU General Public License
            // along with this program.  If not, see <http://www.gnu.org/licenses/>.
            
            /* pragma solidity 0.5.12; */
            
            contract LibNote {
                event LogNote(
                    bytes4   indexed  sig,
                    address  indexed  usr,
                    bytes32  indexed  arg1,
                    bytes32  indexed  arg2,
                    bytes             data
                ) anonymous;
            
                modifier note {
                    _;
                    assembly {
                        // log an 'anonymous' event with a constant 6 words of calldata
                        // and four indexed topics: selector, caller, arg1 and arg2
                        let mark := msize                         // end of memory ensures zero
                        mstore(0x40, add(mark, 288))              // update free memory pointer
                        mstore(mark, 0x20)                        // bytes type data offset
                        mstore(add(mark, 0x20), 224)              // bytes size (padded)
                        calldatacopy(add(mark, 0x40), 0, 224)     // bytes payload
                        log4(mark, 288,                           // calldata
                             shl(224, shr(224, calldataload(0))), // msg.sig
                             caller,                              // msg.sender
                             calldataload(4),                     // arg1
                             calldataload(36)                     // arg2
                            )
                    }
                }
            }
            
            ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/dai.sol
            // Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico
            
            // 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; */
            
            /* import "./lib.sol"; */
            
            contract Dai is LibNote {
                // --- Auth ---
                mapping (address => uint) public wards;
                function rely(address guy) external note auth { wards[guy] = 1; }
                function deny(address guy) external note auth { wards[guy] = 0; }
                modifier auth {
                    require(wards[msg.sender] == 1, "Dai/not-authorized");
                    _;
                }
            
                // --- ERC20 Data ---
                string  public constant name     = "Dai Stablecoin";
                string  public constant symbol   = "DAI";
                string  public constant version  = "1";
                uint8   public constant decimals = 18;
                uint256 public totalSupply;
            
                mapping (address => uint)                      public balanceOf;
                mapping (address => mapping (address => uint)) public allowance;
                mapping (address => uint)                      public nonces;
            
                event Approval(address indexed src, address indexed guy, uint wad);
                event Transfer(address indexed src, address indexed dst, uint wad);
            
                // --- Math ---
                function add(uint x, uint y) internal pure returns (uint z) {
                    require((z = x + y) >= x);
                }
                function sub(uint x, uint y) internal pure returns (uint z) {
                    require((z = x - y) <= x);
                }
            
                // --- EIP712 niceties ---
                bytes32 public DOMAIN_SEPARATOR;
                // bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)");
                bytes32 public constant PERMIT_TYPEHASH = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb;
            
                constructor(uint256 chainId_) public {
                    wards[msg.sender] = 1;
                    DOMAIN_SEPARATOR = keccak256(abi.encode(
                        keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                        keccak256(bytes(name)),
                        keccak256(bytes(version)),
                        chainId_,
                        address(this)
                    ));
                }
            
                // --- Token ---
                function transfer(address dst, uint wad) external returns (bool) {
                    return transferFrom(msg.sender, dst, wad);
                }
                function transferFrom(address src, address dst, uint wad)
                    public returns (bool)
                {
                    require(balanceOf[src] >= wad, "Dai/insufficient-balance");
                    if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) {
                        require(allowance[src][msg.sender] >= wad, "Dai/insufficient-allowance");
                        allowance[src][msg.sender] = sub(allowance[src][msg.sender], wad);
                    }
                    balanceOf[src] = sub(balanceOf[src], wad);
                    balanceOf[dst] = add(balanceOf[dst], wad);
                    emit Transfer(src, dst, wad);
                    return true;
                }
                function mint(address usr, uint wad) external auth {
                    balanceOf[usr] = add(balanceOf[usr], wad);
                    totalSupply    = add(totalSupply, wad);
                    emit Transfer(address(0), usr, wad);
                }
                function burn(address usr, uint wad) external {
                    require(balanceOf[usr] >= wad, "Dai/insufficient-balance");
                    if (usr != msg.sender && allowance[usr][msg.sender] != uint(-1)) {
                        require(allowance[usr][msg.sender] >= wad, "Dai/insufficient-allowance");
                        allowance[usr][msg.sender] = sub(allowance[usr][msg.sender], wad);
                    }
                    balanceOf[usr] = sub(balanceOf[usr], wad);
                    totalSupply    = sub(totalSupply, wad);
                    emit Transfer(usr, address(0), wad);
                }
                function approve(address usr, uint wad) external returns (bool) {
                    allowance[msg.sender][usr] = wad;
                    emit Approval(msg.sender, usr, wad);
                    return true;
                }
            
                // --- Alias ---
                function push(address usr, uint wad) external {
                    transferFrom(msg.sender, usr, wad);
                }
                function pull(address usr, uint wad) external {
                    transferFrom(usr, msg.sender, wad);
                }
                function move(address src, address dst, uint wad) external {
                    transferFrom(src, dst, wad);
                }
            
                // --- Approve by signature ---
                function permit(address holder, address spender, uint256 nonce, uint256 expiry,
                                bool allowed, uint8 v, bytes32 r, bytes32 s) external
                {
                    bytes32 digest =
                        keccak256(abi.encodePacked(
                            "\x19\x01",
                            DOMAIN_SEPARATOR,
                            keccak256(abi.encode(PERMIT_TYPEHASH,
                                                 holder,
                                                 spender,
                                                 nonce,
                                                 expiry,
                                                 allowed))
                    ));
            
                    require(holder != address(0), "Dai/invalid-address-0");
                    require(holder == ecrecover(digest, v, r, s), "Dai/invalid-permit");
                    require(expiry == 0 || now <= expiry, "Dai/permit-expired");
                    require(nonce == nonces[holder]++, "Dai/invalid-nonce");
                    uint wad = allowed ? uint(-1) : 0;
                    allowance[holder][spender] = wad;
                    emit Approval(holder, spender, wad);
                }
            }

            File 4 of 5: DaiJoin
            // hevm: flattened sources of /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/join.sol
            pragma solidity =0.5.12;
            
            ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/lib.sol
            // This program is free software: you can redistribute it and/or modify
            // it under the terms of the GNU 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 General Public License for more details.
            
            // You should have received a copy of the GNU General Public License
            // along with this program.  If not, see <http://www.gnu.org/licenses/>.
            
            /* pragma solidity 0.5.12; */
            
            contract LibNote {
                event LogNote(
                    bytes4   indexed  sig,
                    address  indexed  usr,
                    bytes32  indexed  arg1,
                    bytes32  indexed  arg2,
                    bytes             data
                ) anonymous;
            
                modifier note {
                    _;
                    assembly {
                        // log an 'anonymous' event with a constant 6 words of calldata
                        // and four indexed topics: selector, caller, arg1 and arg2
                        let mark := msize                         // end of memory ensures zero
                        mstore(0x40, add(mark, 288))              // update free memory pointer
                        mstore(mark, 0x20)                        // bytes type data offset
                        mstore(add(mark, 0x20), 224)              // bytes size (padded)
                        calldatacopy(add(mark, 0x40), 0, 224)     // bytes payload
                        log4(mark, 288,                           // calldata
                             shl(224, shr(224, calldataload(0))), // msg.sig
                             caller,                              // msg.sender
                             calldataload(4),                     // arg1
                             calldataload(36)                     // arg2
                            )
                    }
                }
            }
            
            ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/join.sol
            /// join.sol -- Basic token adapters
            
            // Copyright (C) 2018 Rain <rainbreak@riseup.net>
            //
            // 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; */
            
            /* import "./lib.sol"; */
            
            contract GemLike {
                function decimals() public view returns (uint);
                function transfer(address,uint) external returns (bool);
                function transferFrom(address,address,uint) external returns (bool);
            }
            
            contract DSTokenLike {
                function mint(address,uint) external;
                function burn(address,uint) external;
            }
            
            contract VatLike {
                function slip(bytes32,address,int) external;
                function move(address,address,uint) external;
            }
            
            /*
                Here we provide *adapters* to connect the Vat to arbitrary external
                token implementations, creating a bounded context for the Vat. The
                adapters here are provided as working examples:
            
                  - `GemJoin`: For well behaved ERC20 tokens, with simple transfer
                               semantics.
            
                  - `ETHJoin`: For native Ether.
            
                  - `DaiJoin`: For connecting internal Dai balances to an external
                               `DSToken` implementation.
            
                In practice, adapter implementations will be varied and specific to
                individual collateral types, accounting for different transfer
                semantics and token standards.
            
                Adapters need to implement two basic methods:
            
                  - `join`: enter collateral into the system
                  - `exit`: remove collateral from the system
            
            */
            
            contract GemJoin is LibNote {
                // --- Auth ---
                mapping (address => uint) public wards;
                function rely(address usr) external note auth { wards[usr] = 1; }
                function deny(address usr) external note auth { wards[usr] = 0; }
                modifier auth {
                    require(wards[msg.sender] == 1, "GemJoin/not-authorized");
                    _;
                }
            
                VatLike public vat;
                bytes32 public ilk;
                GemLike public gem;
                uint    public dec;
                uint    public live;  // Access Flag
            
                constructor(address vat_, bytes32 ilk_, address gem_) public {
                    wards[msg.sender] = 1;
                    live = 1;
                    vat = VatLike(vat_);
                    ilk = ilk_;
                    gem = GemLike(gem_);
                    dec = gem.decimals();
                }
                function cage() external note auth {
                    live = 0;
                }
                function join(address usr, uint wad) external note {
                    require(live == 1, "GemJoin/not-live");
                    require(int(wad) >= 0, "GemJoin/overflow");
                    vat.slip(ilk, usr, int(wad));
                    require(gem.transferFrom(msg.sender, address(this), wad), "GemJoin/failed-transfer");
                }
                function exit(address usr, uint wad) external note {
                    require(wad <= 2 ** 255, "GemJoin/overflow");
                    vat.slip(ilk, msg.sender, -int(wad));
                    require(gem.transfer(usr, wad), "GemJoin/failed-transfer");
                }
            }
            
            contract ETHJoin is LibNote {
                // --- Auth ---
                mapping (address => uint) public wards;
                function rely(address usr) external note auth { wards[usr] = 1; }
                function deny(address usr) external note auth { wards[usr] = 0; }
                modifier auth {
                    require(wards[msg.sender] == 1, "ETHJoin/not-authorized");
                    _;
                }
            
                VatLike public vat;
                bytes32 public ilk;
                uint    public live;  // Access Flag
            
                constructor(address vat_, bytes32 ilk_) public {
                    wards[msg.sender] = 1;
                    live = 1;
                    vat = VatLike(vat_);
                    ilk = ilk_;
                }
                function cage() external note auth {
                    live = 0;
                }
                function join(address usr) external payable note {
                    require(live == 1, "ETHJoin/not-live");
                    require(int(msg.value) >= 0, "ETHJoin/overflow");
                    vat.slip(ilk, usr, int(msg.value));
                }
                function exit(address payable usr, uint wad) external note {
                    require(int(wad) >= 0, "ETHJoin/overflow");
                    vat.slip(ilk, msg.sender, -int(wad));
                    usr.transfer(wad);
                }
            }
            
            contract DaiJoin is LibNote {
                // --- Auth ---
                mapping (address => uint) public wards;
                function rely(address usr) external note auth { wards[usr] = 1; }
                function deny(address usr) external note auth { wards[usr] = 0; }
                modifier auth {
                    require(wards[msg.sender] == 1, "DaiJoin/not-authorized");
                    _;
                }
            
                VatLike public vat;
                DSTokenLike public dai;
                uint    public live;  // Access Flag
            
                constructor(address vat_, address dai_) public {
                    wards[msg.sender] = 1;
                    live = 1;
                    vat = VatLike(vat_);
                    dai = DSTokenLike(dai_);
                }
                function cage() external note auth {
                    live = 0;
                }
                uint constant ONE = 10 ** 27;
                function mul(uint x, uint y) internal pure returns (uint z) {
                    require(y == 0 || (z = x * y) / y == x);
                }
                function join(address usr, uint wad) external note {
                    vat.move(address(this), usr, mul(ONE, wad));
                    dai.burn(msg.sender, wad);
                }
                function exit(address usr, uint wad) external note {
                    require(live == 1, "DaiJoin/not-live");
                    vat.move(msg.sender, address(this), mul(ONE, wad));
                    dai.mint(usr, wad);
                }
            }

            File 5 of 5: DssProxyActionsDsr
            // hevm: flattened sources of /nix/store/sxr9nv6bdacjzw8vhns72bxjga458x34-dss-proxy-actions-53f1d75/src/DssProxyActions.sol
            pragma solidity =0.5.12;
            
            ////// /nix/store/sxr9nv6bdacjzw8vhns72bxjga458x34-dss-proxy-actions-53f1d75/src/DssProxyActions.sol
            /* pragma solidity 0.5.12; */
            
            contract GemLike {
                function approve(address, uint) public;
                function transfer(address, uint) public;
                function transferFrom(address, address, uint) public;
                function deposit() public payable;
                function withdraw(uint) public;
            }
            
            contract ManagerLike {
                function cdpCan(address, uint, address) public view returns (uint);
                function ilks(uint) public view returns (bytes32);
                function owns(uint) public view returns (address);
                function urns(uint) public view returns (address);
                function vat() public view returns (address);
                function open(bytes32, address) public returns (uint);
                function give(uint, address) public;
                function cdpAllow(uint, address, uint) public;
                function urnAllow(address, uint) public;
                function frob(uint, int, int) public;
                function flux(uint, address, uint) public;
                function move(uint, address, uint) public;
                function exit(address, uint, address, uint) public;
                function quit(uint, address) public;
                function enter(address, uint) public;
                function shift(uint, uint) public;
            }
            
            contract VatLike {
                function can(address, address) public view returns (uint);
                function ilks(bytes32) public view returns (uint, uint, uint, uint, uint);
                function dai(address) public view returns (uint);
                function urns(bytes32, address) public view returns (uint, uint);
                function frob(bytes32, address, address, address, int, int) public;
                function hope(address) public;
                function move(address, address, uint) public;
            }
            
            contract GemJoinLike {
                function dec() public returns (uint);
                function gem() public returns (GemLike);
                function join(address, uint) public payable;
                function exit(address, uint) public;
            }
            
            contract GNTJoinLike {
                function bags(address) public view returns (address);
                function make(address) public returns (address);
            }
            
            contract DaiJoinLike {
                function vat() public returns (VatLike);
                function dai() public returns (GemLike);
                function join(address, uint) public payable;
                function exit(address, uint) public;
            }
            
            contract HopeLike {
                function hope(address) public;
                function nope(address) public;
            }
            
            contract EndLike {
                function fix(bytes32) public view returns (uint);
                function cash(bytes32, uint) public;
                function free(bytes32) public;
                function pack(uint) public;
                function skim(bytes32, address) public;
            }
            
            contract JugLike {
                function drip(bytes32) public returns (uint);
            }
            
            contract PotLike {
                function pie(address) public view returns (uint);
                function drip() public returns (uint);
                function join(uint) public;
                function exit(uint) public;
            }
            
            contract ProxyRegistryLike {
                function proxies(address) public view returns (address);
                function build(address) public returns (address);
            }
            
            contract ProxyLike {
                function owner() public 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 wad) public {
                    GemLike(gem).transfer(dst, wad);
                }
            
                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 wad, 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), wad);
                        // Approves adapter to take the token amount
                        GemJoinLike(apt).gem().approve(apt, wad);
                    }
                    // Joins token collateral into the vat
                    GemJoinLike(apt).join(urn, wad);
                }
            
                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 wad,
                    bool transferFrom
                ) public {
                    // Takes token amount from user's wallet and joins into the vat
                    gemJoin_join(gemJoin, address(this), wad, 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, wad)),
                        0
                    );
                }
            
                function safeLockGem(
                    address manager,
                    address gemJoin,
                    uint cdp,
                    uint wad,
                    bool transferFrom,
                    address owner
                ) public {
                    require(ManagerLike(manager).owns(cdp) == owner, "owner-missmatch");
                    lockGem(manager, gemJoin, cdp, wad, 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 wad
                ) public {
                    uint wad18 = convertTo18(gemJoin, wad);
                    // Unlocks token amount from the CDP
                    frob(manager, cdp, -toInt(wad18), 0);
                    // Moves the amount from the CDP urn to proxy's address
                    flux(manager, cdp, address(this), wad18);
                    // Exits token amount to the user's wallet as a token
                    GemJoinLike(gemJoin).exit(msg.sender, wad);
                }
            
                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 wad
                ) public {
                    // Moves the amount from the CDP urn to proxy's address
                    flux(manager, cdp, address(this), convertTo18(gemJoin, wad));
            
                    // Exits token amount to the user's wallet as a token
                    GemJoinLike(gemJoin).exit(msg.sender, wad);
                }
            
                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 wadC,
                    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, wadC, transferFrom);
                    // Locks token amount into the CDP and generates debt
                    frob(manager, cdp, toInt(convertTo18(gemJoin, wadC)), _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 wadC,
                    uint wadD,
                    bool transferFrom
                ) public returns (uint cdp) {
                    cdp = open(manager, ilk, address(this));
                    lockGemAndDraw(manager, jug, gemJoin, daiJoin, cdp, wadC, wadD, transferFrom);
                }
            
                function openLockGNTAndDraw(
                    address manager,
                    address jug,
                    address gntJoin,
                    address daiJoin,
                    bytes32 ilk,
                    uint wadC,
                    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, wadC);
                    cdp = openLockGemAndDraw(manager, jug, gntJoin, daiJoin, ilk, wadC, 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 wadC,
                    uint wadD
                ) public {
                    address urn = ManagerLike(manager).urns(cdp);
                    // Joins DAI amount into the vat
                    daiJoin_join(daiJoin, urn, wadD);
                    uint wad18 = convertTo18(gemJoin, wadC);
                    // Paybacks debt to the CDP and unlocks token amount from it
                    frob(
                        manager,
                        cdp,
                        -toInt(wad18),
                        _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), wad18);
                    // Exits token amount to the user's wallet as a token
                    GemJoinLike(gemJoin).exit(msg.sender, wadC);
                }
            
                function wipeAllAndFreeGem(
                    address manager,
                    address gemJoin,
                    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));
                    uint wad18 = convertTo18(gemJoin, wadC);
                    // Paybacks debt to the CDP and unlocks token amount from it
                    frob(
                        manager,
                        cdp,
                        -toInt(wad18),
                        -int(art)
                    );
                    // Moves the amount from the CDP urn to proxy's address
                    flux(manager, cdp, address(this), wad18);
                    // Exits token amount to the user's wallet as a token
                    GemJoinLike(gemJoin).exit(msg.sender, wadC);
                }
            }
            
            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 wad = _free(manager, end, cdp);
                    // Exits token amount to the user's wallet as a token
                    GemJoinLike(gemJoin).exit(msg.sender, wad);
                }
            
                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
                    GemJoinLike(gemJoin).exit(msg.sender, mul(wad, EndLike(end).fix(ilk)) / RAY);
                }
            }
            
            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);
                }
            }