ETH Price: $1,884.09 (+1.28%)

Transaction Decoder

Block:
12615206 at Jun-11-2021 07:50:05 PM +UTC
Transaction Fee:
0.002928008505847289 ETH $5.52
Gas Used:
138,709 Gas / 21.109001621 Gwei

Emitted Events:

199 DSProxy.0x1cff79cd00000000000000000000000000000000000000000000000000000000( 0x1cff79cd00000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000e58d06e4475456fbc69b81afdff2f18f6a5d1c31, 0x00000000000000000000000082ecd135dce65fbc6dbdd0e4237e0af93ffd5038, 0x0000000000000000000000000000000000000000000000000000000000000040, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000004000000000, 000000000000000000000000000000000000000000000000000001041cff79cd, 00000000000000000000000082ecd135dce65fbc6dbdd0e4237e0af93ffd5038, 0000000000000000000000000000000000000000000000000000000000000040, 0000000000000000000000000000000000000000000000000000000000000084, 6ab6a4910000000000000000000000005ef30b9986345249bc32d8928b7ee64d, e9435e39000000000000000000000000bf72da2bd84c5170618fbe5914b0eca9, 638d5eb500000000000000000000000000000000000000000000000000000000, 0000349800000000000000000000000000000000000000000000000000000000, 06ea050000000000000000000000000000000000000000000000000000000000 )
200 Vat.0x7608870300000000000000000000000000000000000000000000000000000000( 0x7608870300000000000000000000000000000000000000000000000000000000, 0x574254432d410000000000000000000000000000000000000000000000000000, 0x000000000000000000000000dbb555fa3a5a84d5ede52d43b9c26777d7911f07, 0x000000000000000000000000dbb555fa3a5a84d5ede52d43b9c26777d7911f07, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 76088703574254432d4100000000000000000000000000000000000000000000, 00000000000000000000000000000000dbb555fa3a5a84d5ede52d43b9c26777, d7911f07000000000000000000000000dbb555fa3a5a84d5ede52d43b9c26777, d7911f07000000000000000000000000dbb555fa3a5a84d5ede52d43b9c26777, d7911f07ffffffffffffffffffffffffffffffffffffffffffffffffefe6da25, 5c8c000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
201 DssCdpManager.0x45e6bdcd00000000000000000000000000000000000000000000000000000000( 0x45e6bdcd00000000000000000000000000000000000000000000000000000000, 0x00000000000000000000000007083ef06386266dbb4866f3e8d195a7852ea287, 0x0000000000000000000000000000000000000000000000000000000000003498, 0xffffffffffffffffffffffffffffffffffffffffffffffffefe6da255c8c0000, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 45e6bdcd00000000000000000000000000000000000000000000000000000000, 00003498ffffffffffffffffffffffffffffffffffffffffffffffffefe6da25, 5c8c000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
202 Vat.0x6111be2e00000000000000000000000000000000000000000000000000000000( 0x6111be2e00000000000000000000000000000000000000000000000000000000, 0x574254432d410000000000000000000000000000000000000000000000000000, 0x000000000000000000000000dbb555fa3a5a84d5ede52d43b9c26777d7911f07, 0x00000000000000000000000007083ef06386266dbb4866f3e8d195a7852ea287, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 6111be2e574254432d4100000000000000000000000000000000000000000000, 00000000000000000000000000000000dbb555fa3a5a84d5ede52d43b9c26777, d7911f0700000000000000000000000007083ef06386266dbb4866f3e8d195a7, 852ea287000000000000000000000000000000000000000000000000101925da, a374000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
203 DssCdpManager.0x9bb8f83800000000000000000000000000000000000000000000000000000000( 0x9bb8f83800000000000000000000000000000000000000000000000000000000, 0x00000000000000000000000007083ef06386266dbb4866f3e8d195a7852ea287, 0x0000000000000000000000000000000000000000000000000000000000003498, 0x00000000000000000000000007083ef06386266dbb4866f3e8d195a7852ea287, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 9bb8f83800000000000000000000000000000000000000000000000000000000, 0000349800000000000000000000000007083ef06386266dbb4866f3e8d195a7, 852ea287000000000000000000000000000000000000000000000000101925da, a374000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
204 Vat.0x7cdd3fde00000000000000000000000000000000000000000000000000000000( 0x7cdd3fde00000000000000000000000000000000000000000000000000000000, 0x574254432d410000000000000000000000000000000000000000000000000000, 0x00000000000000000000000007083ef06386266dbb4866f3e8d195a7852ea287, 0xffffffffffffffffffffffffffffffffffffffffffffffffefe6da255c8c0000, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 7cdd3fde574254432d4100000000000000000000000000000000000000000000, 0000000000000000000000000000000007083ef06386266dbb4866f3e8d195a7, 852ea287ffffffffffffffffffffffffffffffffffffffffffffffffefe6da25, 5c8c000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
205 WBTC.Transfer( from=GemJoin5, to=[Sender] 0xe58d06e4475456fbc69b81afdff2f18f6a5d1c31, value=116000000 )
206 GemJoin5.0xef693bed00000000000000000000000000000000000000000000000000000000( 0xef693bed00000000000000000000000000000000000000000000000000000000, 0x00000000000000000000000007083ef06386266dbb4866f3e8d195a7852ea287, 0x000000000000000000000000e58d06e4475456fbc69b81afdff2f18f6a5d1c31, 0x0000000000000000000000000000000000000000000000000000000006ea0500, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, ef693bed000000000000000000000000e58d06e4475456fbc69b81afdff2f18f, 6a5d1c3100000000000000000000000000000000000000000000000000000000, 06ea050000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x2260FAC5...93bc2C599
0x35D1b3F3...259A0492B
(Sky: MCD Vat)
0xE58D06e4...f6A5d1c31
11.218125889881092854 Eth
Nonce: 383
11.215197881375245565 Eth
Nonce: 384
0.002928008505847289
(Ethermine)
640.314183147306331261 Eth640.31711115581217855 Eth0.002928008505847289

Execution Trace

DSProxy.execute( _target=0x82ecD135Dce65Fbc6DbdD0e4237E0AF93FFD5038, _data=0x6AB6A4910000000000000000000000005EF30B9986345249BC32D8928B7EE64DE9435E39000000000000000000000000BF72DA2BD84C5170618FBE5914B0ECA9638D5EB500000000000000000000000000000000000000000000000000000000000034980000000000000000000000000000000000000000000000000000000006EA0500 ) => ( response=0000000000000000000000000000000000000000000000000000000000000000 )
  • DssProxyActions.freeGem( manager=0x5ef30b9986345249bc32d8928B7ee64DE9435E39, gemJoin=0xBF72Da2Bd84c5170618Fbe5914B0ECA9638d5eb5, cdp=13464, wad=116000000 )
    • GemJoin5.CALL( )
    • DssCdpManager.frob( cdp=13464, dink=-1160000000000000000, dart=0 )
      • Vat.frob( i=574254432D410000000000000000000000000000000000000000000000000000, u=0xdBb555fA3a5a84d5EDE52d43B9C26777D7911f07, v=0xdBb555fA3a5a84d5EDE52d43B9C26777D7911f07, w=0xdBb555fA3a5a84d5EDE52d43B9C26777D7911f07, dink=-1160000000000000000, dart=0 )
      • DssCdpManager.flux( cdp=13464, dst=0x07083eF06386266dbB4866f3e8d195A7852eA287, wad=1160000000000000000 )
        • Vat.flux( ilk=574254432D410000000000000000000000000000000000000000000000000000, src=0xdBb555fA3a5a84d5EDE52d43B9C26777D7911f07, dst=0x07083eF06386266dbB4866f3e8d195A7852eA287, wad=1160000000000000000 )
        • GemJoin5.exit( guy=0xE58D06e4475456FbC69b81afdFF2F18f6A5d1c31, wad=116000000 )
          • Vat.slip( ilk=574254432D410000000000000000000000000000000000000000000000000000, usr=0x07083eF06386266dbB4866f3e8d195A7852eA287, wad=-1160000000000000000 )
          • WBTC.transfer( _to=0xE58D06e4475456FbC69b81afdFF2F18f6A5d1c31, _value=116000000 ) => ( True )
            File 1 of 6: DSProxy
            // proxy.sol - execute actions atomically through the proxy's identity
            
            // Copyright (C) 2017  DappHub, LLC
            
            // 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.4.23;
            
            contract DSAuthority {
                function canCall(
                    address src, address dst, bytes4 sig
                ) public view returns (bool);
            }
            
            contract DSAuthEvents {
                event LogSetAuthority (address indexed authority);
                event LogSetOwner     (address indexed owner);
            }
            
            contract DSAuth is DSAuthEvents {
                DSAuthority  public  authority;
                address      public  owner;
            
                constructor() public {
                    owner = msg.sender;
                    emit LogSetOwner(msg.sender);
                }
            
                function setOwner(address owner_)
                    public
                    auth
                {
                    owner = owner_;
                    emit LogSetOwner(owner);
                }
            
                function setAuthority(DSAuthority authority_)
                    public
                    auth
                {
                    authority = authority_;
                    emit LogSetAuthority(authority);
                }
            
                modifier auth {
                    require(isAuthorized(msg.sender, msg.sig));
                    _;
                }
            
                function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
                    if (src == address(this)) {
                        return true;
                    } else if (src == owner) {
                        return true;
                    } else if (authority == DSAuthority(0)) {
                        return false;
                    } else {
                        return authority.canCall(src, this, sig);
                    }
                }
            }
            
            contract DSNote {
                event LogNote(
                    bytes4   indexed  sig,
                    address  indexed  guy,
                    bytes32  indexed  foo,
                    bytes32  indexed  bar,
                    uint              wad,
                    bytes             fax
                ) anonymous;
            
                modifier note {
                    bytes32 foo;
                    bytes32 bar;
            
                    assembly {
                        foo := calldataload(4)
                        bar := calldataload(36)
                    }
            
                    emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
            
                    _;
                }
            }
            
            // DSProxy
            // Allows code execution using a persistant identity This can be very
            // useful to execute a sequence of atomic actions. Since the owner of
            // the proxy can be changed, this allows for dynamic ownership models
            // i.e. a multisig
            contract DSProxy is DSAuth, DSNote {
                DSProxyCache public cache;  // global cache for contracts
            
                constructor(address _cacheAddr) public {
                    require(setCache(_cacheAddr));
                }
            
                function() public payable {
                }
            
                // use the proxy to execute calldata _data on contract _code
                function execute(bytes _code, bytes _data)
                    public
                    payable
                    returns (address target, bytes32 response)
                {
                    target = cache.read(_code);
                    if (target == 0x0) {
                        // deploy contract & store its address in cache
                        target = cache.write(_code);
                    }
            
                    response = execute(target, _data);
                }
            
                function execute(address _target, bytes _data)
                    public
                    auth
                    note
                    payable
                    returns (bytes32 response)
                {
                    require(_target != 0x0);
            
                    // call contract in current context
                    assembly {
                        let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 32)
                        response := mload(0)      // load delegatecall output
                        switch iszero(succeeded)
                        case 1 {
                            // throw if delegatecall failed
                            revert(0, 0)
                        }
                    }
                }
            
                //set new cache
                function setCache(address _cacheAddr)
                    public
                    auth
                    note
                    returns (bool)
                {
                    require(_cacheAddr != 0x0);        // invalid cache address
                    cache = DSProxyCache(_cacheAddr);  // overwrite cache
                    return true;
                }
            }
            
            // DSProxyFactory
            // This factory deploys new proxy instances through build()
            // Deployed proxy addresses are logged
            contract DSProxyFactory {
                event Created(address indexed sender, address indexed owner, address proxy, address cache);
                mapping(address=>bool) public isProxy;
                DSProxyCache public cache = new DSProxyCache();
            
                // deploys a new proxy instance
                // sets owner of proxy to caller
                function build() public returns (DSProxy proxy) {
                    proxy = build(msg.sender);
                }
            
                // deploys a new proxy instance
                // sets custom owner of proxy
                function build(address owner) public returns (DSProxy proxy) {
                    proxy = new DSProxy(cache);
                    emit Created(msg.sender, owner, address(proxy), address(cache));
                    proxy.setOwner(owner);
                    isProxy[proxy] = true;
                }
            }
            
            // DSProxyCache
            // This global cache stores addresses of contracts previously deployed
            // by a proxy. This saves gas from repeat deployment of the same
            // contracts and eliminates blockchain bloat.
            
            // By default, all proxies deployed from the same factory store
            // contracts in the same cache. The cache a proxy instance uses can be
            // changed.  The cache uses the sha3 hash of a contract's bytecode to
            // lookup the address
            contract DSProxyCache {
                mapping(bytes32 => address) cache;
            
                function read(bytes _code) public view returns (address) {
                    bytes32 hash = keccak256(_code);
                    return cache[hash];
                }
            
                function write(bytes _code) public returns (address target) {
                    assembly {
                        target := create(0, add(_code, 0x20), mload(_code))
                        switch iszero(extcodesize(target))
                        case 1 {
                            // throw if contract failed to deploy
                            revert(0, 0)
                        }
                    }
                    bytes32 hash = keccak256(_code);
                    cache[hash] = target;
                }
            }

            File 2 of 6: 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 <[email protected]>
            //
            // 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 3 of 6: DssCdpManager
            // hevm: flattened sources of /nix/store/jyvwn5yyqxwkfxc45k04h2dk209dn6sh-dss-cdp-manager-8976239/src/DssCdpManager.sol
            pragma solidity =0.5.12;
            
            ////// /nix/store/4vip6nyqfd0yhs15md21rzxsk5jgx6sv-dss/dapp/dss/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/jyvwn5yyqxwkfxc45k04h2dk209dn6sh-dss-cdp-manager-8976239/src/DssCdpManager.sol
            /* pragma solidity 0.5.12; */
            
            /* import { LibNote } from "dss/lib.sol"; */
            
            contract VatLike {
                function urns(bytes32, address) public view returns (uint, uint);
                function hope(address) public;
                function flux(bytes32, address, address, uint) public;
                function move(address, address, uint) public;
                function frob(bytes32, address, address, address, int, int) public;
                function fork(bytes32, address, address, int, int) public;
            }
            
            contract UrnHandler {
                constructor(address vat) public {
                    VatLike(vat).hope(msg.sender);
                }
            }
            
            contract DssCdpManager is LibNote {
                address                   public vat;
                uint                      public cdpi;      // Auto incremental
                mapping (uint => address) public urns;      // CDPId => UrnHandler
                mapping (uint => List)    public list;      // CDPId => Prev & Next CDPIds (double linked list)
                mapping (uint => address) public owns;      // CDPId => Owner
                mapping (uint => bytes32) public ilks;      // CDPId => Ilk
            
                mapping (address => uint) public first;     // Owner => First CDPId
                mapping (address => uint) public last;      // Owner => Last CDPId
                mapping (address => uint) public count;     // Owner => Amount of CDPs
            
                mapping (
                    address => mapping (
                        uint => mapping (
                            address => uint
                        )
                    )
                ) public cdpCan;                            // Owner => CDPId => Allowed Addr => True/False
            
                mapping (
                    address => mapping (
                        address => uint
                    )
                ) public urnCan;                            // Urn => Allowed Addr => True/False
            
                struct List {
                    uint prev;
                    uint next;
                }
            
                event NewCdp(address indexed usr, address indexed own, uint indexed cdp);
            
                modifier cdpAllowed(
                    uint cdp
                ) {
                    require(msg.sender == owns[cdp] || cdpCan[owns[cdp]][cdp][msg.sender] == 1, "cdp-not-allowed");
                    _;
                }
            
                modifier urnAllowed(
                    address urn
                ) {
                    require(msg.sender == urn || urnCan[urn][msg.sender] == 1, "urn-not-allowed");
                    _;
                }
            
                constructor(address vat_) public {
                    vat = vat_;
                }
            
                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 toInt(uint x) internal pure returns (int y) {
                    y = int(x);
                    require(y >= 0);
                }
            
                // Allow/disallow a usr address to manage the cdp.
                function cdpAllow(
                    uint cdp,
                    address usr,
                    uint ok
                ) public cdpAllowed(cdp) {
                    cdpCan[owns[cdp]][cdp][usr] = ok;
                }
            
                // Allow/disallow a usr address to quit to the the sender urn.
                function urnAllow(
                    address usr,
                    uint ok
                ) public {
                    urnCan[msg.sender][usr] = ok;
                }
            
                // Open a new cdp for a given usr address.
                function open(
                    bytes32 ilk,
                    address usr
                ) public note returns (uint) {
                    require(usr != address(0), "usr-address-0");
            
                    cdpi = add(cdpi, 1);
                    urns[cdpi] = address(new UrnHandler(vat));
                    owns[cdpi] = usr;
                    ilks[cdpi] = ilk;
            
                    // Add new CDP to double linked list and pointers
                    if (first[usr] == 0) {
                        first[usr] = cdpi;
                    }
                    if (last[usr] != 0) {
                        list[cdpi].prev = last[usr];
                        list[last[usr]].next = cdpi;
                    }
                    last[usr] = cdpi;
                    count[usr] = add(count[usr], 1);
            
                    emit NewCdp(msg.sender, usr, cdpi);
                    return cdpi;
                }
            
                // Give the cdp ownership to a dst address.
                function give(
                    uint cdp,
                    address dst
                ) public note cdpAllowed(cdp) {
                    require(dst != address(0), "dst-address-0");
                    require(dst != owns[cdp], "dst-already-owner");
            
                    // Remove transferred CDP from double linked list of origin user and pointers
                    if (list[cdp].prev != 0) {
                        list[list[cdp].prev].next = list[cdp].next;         // Set the next pointer of the prev cdp (if exists) to the next of the transferred one
                    }
                    if (list[cdp].next != 0) {                              // If wasn't the last one
                        list[list[cdp].next].prev = list[cdp].prev;         // Set the prev pointer of the next cdp to the prev of the transferred one
                    } else {                                                // If was the last one
                        last[owns[cdp]] = list[cdp].prev;                   // Update last pointer of the owner
                    }
                    if (first[owns[cdp]] == cdp) {                          // If was the first one
                        first[owns[cdp]] = list[cdp].next;                  // Update first pointer of the owner
                    }
                    count[owns[cdp]] = sub(count[owns[cdp]], 1);
            
                    // Transfer ownership
                    owns[cdp] = dst;
            
                    // Add transferred CDP to double linked list of destiny user and pointers
                    list[cdp].prev = last[dst];
                    list[cdp].next = 0;
                    if (last[dst] != 0) {
                        list[last[dst]].next = cdp;
                    }
                    if (first[dst] == 0) {
                        first[dst] = cdp;
                    }
                    last[dst] = cdp;
                    count[dst] = add(count[dst], 1);
                }
            
                // Frob the cdp keeping the generated DAI or collateral freed in the cdp urn address.
                function frob(
                    uint cdp,
                    int dink,
                    int dart
                ) public note cdpAllowed(cdp) {
                    address urn = urns[cdp];
                    VatLike(vat).frob(
                        ilks[cdp],
                        urn,
                        urn,
                        urn,
                        dink,
                        dart
                    );
                }
            
                // Transfer wad amount of cdp collateral from the cdp address to a dst address.
                function flux(
                    uint cdp,
                    address dst,
                    uint wad
                ) public note cdpAllowed(cdp) {
                    VatLike(vat).flux(ilks[cdp], urns[cdp], dst, wad);
                }
            
                // Transfer wad amount of any type of collateral (ilk) from the cdp address to a dst address.
                // This function has the purpose to take away collateral from the system that doesn't correspond to the cdp but was sent there wrongly.
                function flux(
                    bytes32 ilk,
                    uint cdp,
                    address dst,
                    uint wad
                ) public note cdpAllowed(cdp) {
                    VatLike(vat).flux(ilk, urns[cdp], dst, wad);
                }
            
                // Transfer wad amount of DAI from the cdp address to a dst address.
                function move(
                    uint cdp,
                    address dst,
                    uint rad
                ) public note cdpAllowed(cdp) {
                    VatLike(vat).move(urns[cdp], dst, rad);
                }
            
                // Quit the system, migrating the cdp (ink, art) to a different dst urn
                function quit(
                    uint cdp,
                    address dst
                ) public note cdpAllowed(cdp) urnAllowed(dst) {
                    (uint ink, uint art) = VatLike(vat).urns(ilks[cdp], urns[cdp]);
                    VatLike(vat).fork(
                        ilks[cdp],
                        urns[cdp],
                        dst,
                        toInt(ink),
                        toInt(art)
                    );
                }
            
                // Import a position from src urn to the urn owned by cdp
                function enter(
                    address src,
                    uint cdp
                ) public note urnAllowed(src) cdpAllowed(cdp) {
                    (uint ink, uint art) = VatLike(vat).urns(ilks[cdp], src);
                    VatLike(vat).fork(
                        ilks[cdp],
                        src,
                        urns[cdp],
                        toInt(ink),
                        toInt(art)
                    );
                }
            
                // Move a position from cdpSrc urn to the cdpDst urn
                function shift(
                    uint cdpSrc,
                    uint cdpDst
                ) public note cdpAllowed(cdpSrc) cdpAllowed(cdpDst) {
                    require(ilks[cdpSrc] == ilks[cdpDst], "non-matching-cdps");
                    (uint ink, uint art) = VatLike(vat).urns(ilks[cdpSrc], urns[cdpSrc]);
                    VatLike(vat).fork(
                        ilks[cdpSrc],
                        urns[cdpSrc],
                        urns[cdpDst],
                        toInt(ink),
                        toInt(art)
                    );
                }
            }

            File 4 of 6: GemJoin5
            /// join.sol -- Non-standard token adapters
            
            // Copyright (C) 2018 Rain <[email protected]>
            //
            // 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 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
                            )
                    }
                }
            }
            
            contract VatLike {
                function slip(bytes32,address,int) public;
            }
            
            contract GemLike5 {
                function decimals() public view returns (uint8);
                function transfer(address,uint) public returns (bool);
                function transferFrom(address,address,uint) public returns (bool);
            }
            
            contract GemJoin5 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); _; }
            
                VatLike  public vat;
                bytes32  public ilk;
                GemLike5 public gem;
                uint     public dec;
                uint     public live;  // Access Flag
            
                constructor(address vat_, bytes32 ilk_, address gem_) public {
                    gem = GemLike5(gem_);
                    dec = gem.decimals();
                    require(dec < 18, "GemJoin5/decimals-18-or-higher");
                    wards[msg.sender] = 1;
                    live = 1;
                    vat = VatLike(vat_);
                    ilk = ilk_;
                }
            
                function cage() external note auth {
                    live = 0;
                }
            
                function mul(uint x, uint y) internal pure returns (uint z) {
                    require(y == 0 || (z = x * y) / y == x, "GemJoin5/overflow");
                }
            
                function join(address urn, uint wad) public note {
                    require(live == 1, "GemJoin5/not-live");
                    uint wad18 = mul(wad, 10 ** (18 - dec));
                    require(int(wad18) >= 0, "GemJoin5/overflow");
                    vat.slip(ilk, urn, int(wad18));
                    require(gem.transferFrom(msg.sender, address(this), wad), "GemJoin5/failed-transfer");
                }
            
                function exit(address guy, uint wad) public note {
                    uint wad18 = mul(wad, 10 ** (18 - dec));
                    require(int(wad18) >= 0, "GemJoin5/overflow");
                    vat.slip(ilk, msg.sender, -int(wad18));
                    require(gem.transfer(guy, wad), "GemJoin5/failed-transfer");
                }
            }

            File 5 of 6: WBTC
            pragma solidity 0.4.24;
            
            // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol
            
            /**
             * @title ERC20Basic
             * @dev Simpler version of ERC20 interface
             * See https://github.com/ethereum/EIPs/issues/179
             */
            contract ERC20Basic {
              function totalSupply() public view returns (uint256);
              function balanceOf(address _who) public view returns (uint256);
              function transfer(address _to, uint256 _value) public returns (bool);
              event Transfer(address indexed from, address indexed to, uint256 value);
            }
            
            // File: openzeppelin-solidity/contracts/math/SafeMath.sol
            
            /**
             * @title SafeMath
             * @dev Math operations with safety checks that throw on error
             */
            library SafeMath {
            
              /**
              * @dev Multiplies two numbers, throws on overflow.
              */
              function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
                // benefit is lost if 'b' is also tested.
                // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                if (_a == 0) {
                  return 0;
                }
            
                c = _a * _b;
                assert(c / _a == _b);
                return c;
              }
            
              /**
              * @dev Integer division of two numbers, truncating the quotient.
              */
              function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
                // assert(_b > 0); // Solidity automatically throws when dividing by 0
                // uint256 c = _a / _b;
                // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold
                return _a / _b;
              }
            
              /**
              * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
              */
              function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
                assert(_b <= _a);
                return _a - _b;
              }
            
              /**
              * @dev Adds two numbers, throws on overflow.
              */
              function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                c = _a + _b;
                assert(c >= _a);
                return c;
              }
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/BasicToken.sol
            
            /**
             * @title Basic token
             * @dev Basic version of StandardToken, with no allowances.
             */
            contract BasicToken is ERC20Basic {
              using SafeMath for uint256;
            
              mapping(address => uint256) internal balances;
            
              uint256 internal totalSupply_;
            
              /**
              * @dev Total number of tokens in existence
              */
              function totalSupply() public view returns (uint256) {
                return totalSupply_;
              }
            
              /**
              * @dev Transfer token for a specified address
              * @param _to The address to transfer to.
              * @param _value The amount to be transferred.
              */
              function transfer(address _to, uint256 _value) public returns (bool) {
                require(_value <= balances[msg.sender]);
                require(_to != address(0));
            
                balances[msg.sender] = balances[msg.sender].sub(_value);
                balances[_to] = balances[_to].add(_value);
                emit Transfer(msg.sender, _to, _value);
                return true;
              }
            
              /**
              * @dev Gets the balance of the specified address.
              * @param _owner The address to query the the balance of.
              * @return An uint256 representing the amount owned by the passed address.
              */
              function balanceOf(address _owner) public view returns (uint256) {
                return balances[_owner];
              }
            
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
            
            /**
             * @title ERC20 interface
             * @dev see https://github.com/ethereum/EIPs/issues/20
             */
            contract ERC20 is ERC20Basic {
              function allowance(address _owner, address _spender)
                public view returns (uint256);
            
              function transferFrom(address _from, address _to, uint256 _value)
                public returns (bool);
            
              function approve(address _spender, uint256 _value) public returns (bool);
              event Approval(
                address indexed owner,
                address indexed spender,
                uint256 value
              );
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol
            
            /**
             * @title Standard ERC20 token
             *
             * @dev Implementation of the basic standard token.
             * https://github.com/ethereum/EIPs/issues/20
             * Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
             */
            contract StandardToken is ERC20, BasicToken {
            
              mapping (address => mapping (address => uint256)) internal allowed;
            
            
              /**
               * @dev Transfer tokens from one address to another
               * @param _from address The address which you want to send tokens from
               * @param _to address The address which you want to transfer to
               * @param _value uint256 the amount of tokens to be transferred
               */
              function transferFrom(
                address _from,
                address _to,
                uint256 _value
              )
                public
                returns (bool)
              {
                require(_value <= balances[_from]);
                require(_value <= allowed[_from][msg.sender]);
                require(_to != address(0));
            
                balances[_from] = balances[_from].sub(_value);
                balances[_to] = balances[_to].add(_value);
                allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
                emit Transfer(_from, _to, _value);
                return true;
              }
            
              /**
               * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
               * Beware that changing an allowance with this method brings the risk that someone may use both the old
               * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
               * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
               * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
               * @param _spender The address which will spend the funds.
               * @param _value The amount of tokens to be spent.
               */
              function approve(address _spender, uint256 _value) public returns (bool) {
                allowed[msg.sender][_spender] = _value;
                emit Approval(msg.sender, _spender, _value);
                return true;
              }
            
              /**
               * @dev Function to check the amount of tokens that an owner allowed to a spender.
               * @param _owner address The address which owns the funds.
               * @param _spender address The address which will spend the funds.
               * @return A uint256 specifying the amount of tokens still available for the spender.
               */
              function allowance(
                address _owner,
                address _spender
               )
                public
                view
                returns (uint256)
              {
                return allowed[_owner][_spender];
              }
            
              /**
               * @dev Increase the amount of tokens that an owner allowed to a spender.
               * approve should be called when allowed[_spender] == 0. To increment
               * allowed value is better to use this function to avoid 2 calls (and wait until
               * the first transaction is mined)
               * From MonolithDAO Token.sol
               * @param _spender The address which will spend the funds.
               * @param _addedValue The amount of tokens to increase the allowance by.
               */
              function increaseApproval(
                address _spender,
                uint256 _addedValue
              )
                public
                returns (bool)
              {
                allowed[msg.sender][_spender] = (
                  allowed[msg.sender][_spender].add(_addedValue));
                emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
                return true;
              }
            
              /**
               * @dev Decrease the amount of tokens that an owner allowed to a spender.
               * approve should be called when allowed[_spender] == 0. To decrement
               * allowed value is better to use this function to avoid 2 calls (and wait until
               * the first transaction is mined)
               * From MonolithDAO Token.sol
               * @param _spender The address which will spend the funds.
               * @param _subtractedValue The amount of tokens to decrease the allowance by.
               */
              function decreaseApproval(
                address _spender,
                uint256 _subtractedValue
              )
                public
                returns (bool)
              {
                uint256 oldValue = allowed[msg.sender][_spender];
                if (_subtractedValue >= oldValue) {
                  allowed[msg.sender][_spender] = 0;
                } else {
                  allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
                }
                emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
                return true;
              }
            
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol
            
            /**
             * @title DetailedERC20 token
             * @dev The decimals are only for visualization purposes.
             * All the operations are done using the smallest and indivisible token unit,
             * just as on Ethereum all the operations are done in wei.
             */
            contract DetailedERC20 is ERC20 {
              string public name;
              string public symbol;
              uint8 public decimals;
            
              constructor(string _name, string _symbol, uint8 _decimals) public {
                name = _name;
                symbol = _symbol;
                decimals = _decimals;
              }
            }
            
            // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
            
            /**
             * @title Ownable
             * @dev The Ownable contract has an owner address, and provides basic authorization control
             * functions, this simplifies the implementation of "user permissions".
             */
            contract Ownable {
              address public owner;
            
            
              event OwnershipRenounced(address indexed previousOwner);
              event OwnershipTransferred(
                address indexed previousOwner,
                address indexed newOwner
              );
            
            
              /**
               * @dev The Ownable constructor sets the original `owner` of the contract to the sender
               * account.
               */
              constructor() public {
                owner = msg.sender;
              }
            
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                require(msg.sender == owner);
                _;
              }
            
              /**
               * @dev Allows the current owner to relinquish control of the contract.
               * @notice Renouncing to ownership will leave the contract without an owner.
               * It will not be possible to call the functions with the `onlyOwner`
               * modifier anymore.
               */
              function renounceOwnership() public onlyOwner {
                emit OwnershipRenounced(owner);
                owner = address(0);
              }
            
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param _newOwner The address to transfer ownership to.
               */
              function transferOwnership(address _newOwner) public onlyOwner {
                _transferOwnership(_newOwner);
              }
            
              /**
               * @dev Transfers control of the contract to a newOwner.
               * @param _newOwner The address to transfer ownership to.
               */
              function _transferOwnership(address _newOwner) internal {
                require(_newOwner != address(0));
                emit OwnershipTransferred(owner, _newOwner);
                owner = _newOwner;
              }
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/MintableToken.sol
            
            /**
             * @title Mintable token
             * @dev Simple ERC20 Token example, with mintable token creation
             * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
             */
            contract MintableToken is StandardToken, Ownable {
              event Mint(address indexed to, uint256 amount);
              event MintFinished();
            
              bool public mintingFinished = false;
            
            
              modifier canMint() {
                require(!mintingFinished);
                _;
              }
            
              modifier hasMintPermission() {
                require(msg.sender == owner);
                _;
              }
            
              /**
               * @dev Function to mint tokens
               * @param _to The address that will receive the minted tokens.
               * @param _amount The amount of tokens to mint.
               * @return A boolean that indicates if the operation was successful.
               */
              function mint(
                address _to,
                uint256 _amount
              )
                public
                hasMintPermission
                canMint
                returns (bool)
              {
                totalSupply_ = totalSupply_.add(_amount);
                balances[_to] = balances[_to].add(_amount);
                emit Mint(_to, _amount);
                emit Transfer(address(0), _to, _amount);
                return true;
              }
            
              /**
               * @dev Function to stop minting new tokens.
               * @return True if the operation was successful.
               */
              function finishMinting() public onlyOwner canMint returns (bool) {
                mintingFinished = true;
                emit MintFinished();
                return true;
              }
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/BurnableToken.sol
            
            /**
             * @title Burnable Token
             * @dev Token that can be irreversibly burned (destroyed).
             */
            contract BurnableToken is BasicToken {
            
              event Burn(address indexed burner, uint256 value);
            
              /**
               * @dev Burns a specific amount of tokens.
               * @param _value The amount of token to be burned.
               */
              function burn(uint256 _value) public {
                _burn(msg.sender, _value);
              }
            
              function _burn(address _who, uint256 _value) internal {
                require(_value <= balances[_who]);
                // no need to require value <= totalSupply, since that would imply the
                // sender's balance is greater than the totalSupply, which *should* be an assertion failure
            
                balances[_who] = balances[_who].sub(_value);
                totalSupply_ = totalSupply_.sub(_value);
                emit Burn(_who, _value);
                emit Transfer(_who, address(0), _value);
              }
            }
            
            // File: openzeppelin-solidity/contracts/lifecycle/Pausable.sol
            
            /**
             * @title Pausable
             * @dev Base contract which allows children to implement an emergency stop mechanism.
             */
            contract Pausable is Ownable {
              event Pause();
              event Unpause();
            
              bool public paused = false;
            
            
              /**
               * @dev Modifier to make a function callable only when the contract is not paused.
               */
              modifier whenNotPaused() {
                require(!paused);
                _;
              }
            
              /**
               * @dev Modifier to make a function callable only when the contract is paused.
               */
              modifier whenPaused() {
                require(paused);
                _;
              }
            
              /**
               * @dev called by the owner to pause, triggers stopped state
               */
              function pause() public onlyOwner whenNotPaused {
                paused = true;
                emit Pause();
              }
            
              /**
               * @dev called by the owner to unpause, returns to normal state
               */
              function unpause() public onlyOwner whenPaused {
                paused = false;
                emit Unpause();
              }
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/PausableToken.sol
            
            /**
             * @title Pausable token
             * @dev StandardToken modified with pausable transfers.
             **/
            contract PausableToken is StandardToken, Pausable {
            
              function transfer(
                address _to,
                uint256 _value
              )
                public
                whenNotPaused
                returns (bool)
              {
                return super.transfer(_to, _value);
              }
            
              function transferFrom(
                address _from,
                address _to,
                uint256 _value
              )
                public
                whenNotPaused
                returns (bool)
              {
                return super.transferFrom(_from, _to, _value);
              }
            
              function approve(
                address _spender,
                uint256 _value
              )
                public
                whenNotPaused
                returns (bool)
              {
                return super.approve(_spender, _value);
              }
            
              function increaseApproval(
                address _spender,
                uint _addedValue
              )
                public
                whenNotPaused
                returns (bool success)
              {
                return super.increaseApproval(_spender, _addedValue);
              }
            
              function decreaseApproval(
                address _spender,
                uint _subtractedValue
              )
                public
                whenNotPaused
                returns (bool success)
              {
                return super.decreaseApproval(_spender, _subtractedValue);
              }
            }
            
            // File: openzeppelin-solidity/contracts/ownership/Claimable.sol
            
            /**
             * @title Claimable
             * @dev Extension for the Ownable contract, where the ownership needs to be claimed.
             * This allows the new owner to accept the transfer.
             */
            contract Claimable is Ownable {
              address public pendingOwner;
            
              /**
               * @dev Modifier throws if called by any account other than the pendingOwner.
               */
              modifier onlyPendingOwner() {
                require(msg.sender == pendingOwner);
                _;
              }
            
              /**
               * @dev Allows the current owner to set the pendingOwner address.
               * @param newOwner The address to transfer ownership to.
               */
              function transferOwnership(address newOwner) public onlyOwner {
                pendingOwner = newOwner;
              }
            
              /**
               * @dev Allows the pendingOwner address to finalize the transfer.
               */
              function claimOwnership() public onlyPendingOwner {
                emit OwnershipTransferred(owner, pendingOwner);
                owner = pendingOwner;
                pendingOwner = address(0);
              }
            }
            
            // File: openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol
            
            /**
             * @title SafeERC20
             * @dev Wrappers around ERC20 operations that throw on failure.
             * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
             * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
             */
            library SafeERC20 {
              function safeTransfer(
                ERC20Basic _token,
                address _to,
                uint256 _value
              )
                internal
              {
                require(_token.transfer(_to, _value));
              }
            
              function safeTransferFrom(
                ERC20 _token,
                address _from,
                address _to,
                uint256 _value
              )
                internal
              {
                require(_token.transferFrom(_from, _to, _value));
              }
            
              function safeApprove(
                ERC20 _token,
                address _spender,
                uint256 _value
              )
                internal
              {
                require(_token.approve(_spender, _value));
              }
            }
            
            // File: openzeppelin-solidity/contracts/ownership/CanReclaimToken.sol
            
            /**
             * @title Contracts that should be able to recover tokens
             * @author SylTi
             * @dev This allow a contract to recover any ERC20 token received in a contract by transferring the balance to the contract owner.
             * This will prevent any accidental loss of tokens.
             */
            contract CanReclaimToken is Ownable {
              using SafeERC20 for ERC20Basic;
            
              /**
               * @dev Reclaim all ERC20Basic compatible tokens
               * @param _token ERC20Basic The address of the token contract
               */
              function reclaimToken(ERC20Basic _token) external onlyOwner {
                uint256 balance = _token.balanceOf(this);
                _token.safeTransfer(owner, balance);
              }
            
            }
            
            // File: contracts/utils/OwnableContract.sol
            
            // empty block is used as this contract just inherits others.
            contract OwnableContract is CanReclaimToken, Claimable { } /* solhint-disable-line no-empty-blocks */
            
            // File: contracts/token/WBTC.sol
            
            contract WBTC is StandardToken, DetailedERC20("Wrapped BTC", "WBTC", 8),
                MintableToken, BurnableToken, PausableToken, OwnableContract {
            
                function burn(uint value) public onlyOwner {
                    super.burn(value);
                }
            
                function finishMinting() public onlyOwner returns (bool) {
                    return false;
                }
            
                function renounceOwnership() public onlyOwner {
                    revert("renouncing ownership is blocked");
                }
            }

            File 6 of 6: DssProxyActions
            // 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);
                }
            }