ETH Price: $1,872.66 (-0.29%)

Transaction Decoder

Block:
9006061 at Nov-26-2019 08:23:28 PM +UTC
Transaction Fee:
0.001526904 ETH $2.86
Gas Used:
254,484 Gas / 6 Gwei

Emitted Events:

48 DSProxy.0x1cff79cd00000000000000000000000000000000000000000000000000000000( 0x1cff79cd00000000000000000000000000000000000000000000000000000000, 0x00000000000000000000000051d0885b47ecd9ad3eecc322407d2c89f70bc00b, 0x000000000000000000000000e4b22d484958e582098a98229a24e8a43801b674, 0x0000000000000000000000000000000000000000000000000000000000000040, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000004000000000, 000000000000000000000000000000000000000000000000000000c41cff79cd, 000000000000000000000000e4b22d484958e582098a98229a24e8a43801b674, 0000000000000000000000000000000000000000000000000000000000000040, 0000000000000000000000000000000000000000000000000000000000000044, 8c544246000000000000000000000000c73e0383f3aff3215e6f04b0331d58ce, cf0ab849000000000000000000000000000000000000000000000002e1acd90d, b88c66a100000000000000000000000000000000000000000000000000000000 )
49 DSToken.Transfer( src=[Sender] 0x51d0885b47ecd9ad3eecc322407d2c89f70bc00b, dst=[Receiver] DSProxy, wad=53155099154901132961 )
50 DSToken.Approval( src=[Receiver] DSProxy, guy=ScdMcdMigration, wad=53155099154901132961 )
51 DSToken.Transfer( src=[Receiver] DSProxy, dst=ScdMcdMigration, wad=53155099154901132961 )
52 Vat.0x7cdd3fde00000000000000000000000000000000000000000000000000000000( 0x7cdd3fde00000000000000000000000000000000000000000000000000000000, 0x5341490000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000c73e0383f3aff3215e6f04b0331d58cecf0ab849, 0x000000000000000000000000000000000000000000000002e1acd90db88c66a1, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 7cdd3fde53414900000000000000000000000000000000000000000000000000, 00000000000000000000000000000000c73e0383f3aff3215e6f04b0331d58ce, cf0ab849000000000000000000000000000000000000000000000002e1acd90d, b88c66a100000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
53 DSToken.Transfer( src=ScdMcdMigration, dst=AuthGemJoin, wad=53155099154901132961 )
54 AuthGemJoin.0x3b4da69f00000000000000000000000000000000000000000000000000000000( 0x3b4da69f00000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000c73e0383f3aff3215e6f04b0331d58cecf0ab849, 0x000000000000000000000000c73e0383f3aff3215e6f04b0331d58cecf0ab849, 0x000000000000000000000000000000000000000000000002e1acd90db88c66a1, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 3b4da69f000000000000000000000000c73e0383f3aff3215e6f04b0331d58ce, cf0ab849000000000000000000000000000000000000000000000002e1acd90d, b88c66a100000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
55 Vat.0x7608870300000000000000000000000000000000000000000000000000000000( 0x7608870300000000000000000000000000000000000000000000000000000000, 0x5341490000000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000c73e0383f3aff3215e6f04b0331d58cecf0ab849, 0x000000000000000000000000c73e0383f3aff3215e6f04b0331d58cecf0ab849, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 7608870353414900000000000000000000000000000000000000000000000000, 00000000000000000000000000000000c73e0383f3aff3215e6f04b0331d58ce, cf0ab849000000000000000000000000c73e0383f3aff3215e6f04b0331d58ce, cf0ab849000000000000000000000000c73e0383f3aff3215e6f04b0331d58ce, cf0ab849000000000000000000000000000000000000000000000002e1acd90d, b88c66a1000000000000000000000000000000000000000000000002e1acd90d, b88c66a100000000000000000000000000000000000000000000000000000000 )
56 Vat.0xbb35783b00000000000000000000000000000000000000000000000000000000( 0xbb35783b00000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000c73e0383f3aff3215e6f04b0331d58cecf0ab849, 0x0000000000000000000000009759a6ac90977b93b58547b4a71c78317f391a28, 0x000000000000000000000000094f8e9cef59acb5d3c781bf4547cabde8000000, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, bb35783b000000000000000000000000c73e0383f3aff3215e6f04b0331d58ce, cf0ab8490000000000000000000000009759a6ac90977b93b58547b4a71c7831, 7f391a28000000000000000000000000094f8e9cef59acb5d3c781bf4547cabd, e800000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
57 Dai.Transfer( src=0x0000000000000000000000000000000000000000, dst=[Receiver] DSProxy, wad=53155099154901132961 )
58 DaiJoin.0xef693bed00000000000000000000000000000000000000000000000000000000( 0xef693bed00000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000c73e0383f3aff3215e6f04b0331d58cecf0ab849, 0x0000000000000000000000002161d0eabb0d52dae718861402d2c77751b66bae, 0x000000000000000000000000000000000000000000000002e1acd90db88c66a1, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, ef693bed0000000000000000000000002161d0eabb0d52dae718861402d2c777, 51b66bae000000000000000000000000000000000000000000000002e1acd90d, b88c66a100000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
59 Dai.Transfer( src=[Receiver] DSProxy, dst=[Sender] 0x51d0885b47ecd9ad3eecc322407d2c89f70bc00b, wad=53155099154901132961 )

Account State Difference:

  Address   Before After State Difference Code
0x35D1b3F3...259A0492B
(Sky: MCD Vat)
(firepool)
110.473438546317615382 Eth110.474965450317615382 Eth0.001526904
0x51D0885B...9f70BC00b
0.832938791298183861 Eth
Nonce: 51
0.831411887298183861 Eth
Nonce: 52
0.001526904
0x6B175474...495271d0F
0x89d24A6b...a23260359

Execution Trace

DSProxy.execute( _target=0xe4B22D484958E582098A98229A24e8A43801b674, _data=0x8C544246000000000000000000000000C73E0383F3AFF3215E6F04B0331D58CECF0AB849000000000000000000000000000000000000000000000002E1ACD90DB88C66A1 ) => ( response=0000000000000000000000000000000000000000000000000000000000000000 )
  • MigrationProxyActions.swapSaiToDai( scdMcdMigration=0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849, wad=53155099154901132961 )
    • ScdMcdMigration.STATICCALL( )
    • SaiTub.STATICCALL( )
    • ScdMcdMigration.STATICCALL( )
    • DaiJoin.CALL( )
    • DSToken.transferFrom( src=0x51D0885B47eCD9ad3eECC322407d2c89f70BC00b, dst=0x2161D0eabB0d52dAe718861402D2c77751B66bAE, wad=53155099154901132961 ) => ( True )
    • DSToken.allowance( src=0x2161D0eabB0d52dAe718861402D2c77751B66bAE, guy=0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849 ) => ( 0 )
    • DSToken.approve( guy=0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849, wad=53155099154901132961 ) => ( True )
    • ScdMcdMigration.swapSaiToDai( wad=53155099154901132961 )
      • AuthGemJoin.CALL( )
      • DSToken.transferFrom( src=0x2161D0eabB0d52dAe718861402D2c77751B66bAE, dst=0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849, wad=53155099154901132961 ) => ( True )
      • AuthGemJoin.join( usr=0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849, wad=53155099154901132961 )
        • Vat.slip( ilk=5341490000000000000000000000000000000000000000000000000000000000, usr=0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849, wad=53155099154901132961 )
        • DSToken.transferFrom( src=0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849, dst=0xad37fd42185Ba63009177058208dd1be4b136e6b, wad=53155099154901132961 ) => ( True )
        • AuthGemJoin.CALL( )
        • Vat.frob( i=5341490000000000000000000000000000000000000000000000000000000000, u=0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849, v=0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849, w=0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849, dink=53155099154901132961, dart=53155099154901132961 )
        • DaiJoin.exit( usr=0x2161D0eabB0d52dAe718861402D2c77751B66bAE, wad=53155099154901132961 )
          • Vat.move( src=0xc73e0383F3Aff3215E6f04B0331D58CeCf0Ab849, dst=0x9759A6Ac90977b93B58547b4A71c78317f391A28, rad=53155099154901132961000000000000000000000000000 )
          • Dai.mint( usr=0x2161D0eabB0d52dAe718861402D2c77751B66bAE, wad=53155099154901132961 )
          • Dai.transfer( dst=0x51D0885B47eCD9ad3eECC322407d2c89f70BC00b, wad=53155099154901132961 ) => ( True )
            File 1 of 9: 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 9: DSToken
            pragma solidity ^0.4.13;
            
            ////// lib/ds-math/src/math.sol
            /// math.sol -- mixin for inline numerical wizardry
            
            // 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.13; */
            
            contract DSMath {
                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);
                }
            
                function min(uint x, uint y) internal pure returns (uint z) {
                    return x <= y ? x : y;
                }
                function max(uint x, uint y) internal pure returns (uint z) {
                    return x >= y ? x : y;
                }
                function imin(int x, int y) internal pure returns (int z) {
                    return x <= y ? x : y;
                }
                function imax(int x, int y) internal pure returns (int z) {
                    return x >= y ? x : y;
                }
            
                uint constant WAD = 10 ** 18;
                uint constant RAY = 10 ** 27;
            
                function wmul(uint x, uint y) internal pure returns (uint z) {
                    z = add(mul(x, y), WAD / 2) / WAD;
                }
                function rmul(uint x, uint y) internal pure returns (uint z) {
                    z = add(mul(x, y), RAY / 2) / RAY;
                }
                function wdiv(uint x, uint y) internal pure returns (uint z) {
                    z = add(mul(x, WAD), y / 2) / y;
                }
                function rdiv(uint x, uint y) internal pure returns (uint z) {
                    z = add(mul(x, RAY), y / 2) / y;
                }
            
                // This famous algorithm is called "exponentiation by squaring"
                // and calculates x^n with x as fixed-point and n as regular unsigned.
                //
                // It's O(log n), instead of O(n) for naive repeated multiplication.
                //
                // These facts are why it works:
                //
                //  If n is even, then x^n = (x^2)^(n/2).
                //  If n is odd,  then x^n = x * x^(n-1),
                //   and applying the equation for even x gives
                //    x^n = x * (x^2)^((n-1) / 2).
                //
                //  Also, EVM division is flooring and
                //    floor[(n-1) / 2] = floor[n / 2].
                //
                function rpow(uint x, uint n) internal pure returns (uint z) {
                    z = n % 2 != 0 ? x : RAY;
            
                    for (n /= 2; n != 0; n /= 2) {
                        x = rmul(x, x);
            
                        if (n % 2 != 0) {
                            z = rmul(z, x);
                        }
                    }
                }
            }
            
            ////// lib/ds-stop/lib/ds-auth/src/auth.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.4.13; */
            
            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;
            
                function DSAuth() public {
                    owner = msg.sender;
                    LogSetOwner(msg.sender);
                }
            
                function setOwner(address owner_)
                    public
                    auth
                {
                    owner = owner_;
                    LogSetOwner(owner);
                }
            
                function setAuthority(DSAuthority authority_)
                    public
                    auth
                {
                    authority = authority_;
                    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);
                    }
                }
            }
            
            ////// lib/ds-stop/lib/ds-note/src/note.sol
            /// note.sol -- the `note' modifier, for logging calls as events
            
            // 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.13; */
            
            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)
                    }
            
                    LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
            
                    _;
                }
            }
            
            ////// lib/ds-stop/src/stop.sol
            /// stop.sol -- mixin for enable/disable functionality
            
            // 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.13; */
            
            /* import "ds-auth/auth.sol"; */
            /* import "ds-note/note.sol"; */
            
            contract DSStop is DSNote, DSAuth {
            
                bool public stopped;
            
                modifier stoppable {
                    require(!stopped);
                    _;
                }
                function stop() public auth note {
                    stopped = true;
                }
                function start() public auth note {
                    stopped = false;
                }
            
            }
            
            ////// lib/erc20/src/erc20.sol
            /// erc20.sol -- API for the ERC20 token standard
            
            // See <https://github.com/ethereum/EIPs/issues/20>.
            
            // This file likely does not meet the threshold of originality
            // required for copyright to apply.  As a result, this is free and
            // unencumbered software belonging to the public domain.
            
            /* pragma solidity ^0.4.8; */
            
            contract ERC20Events {
                event Approval(address indexed src, address indexed guy, uint wad);
                event Transfer(address indexed src, address indexed dst, uint wad);
            }
            
            contract ERC20 is ERC20Events {
                function totalSupply() public view returns (uint);
                function balanceOf(address guy) public view returns (uint);
                function allowance(address src, address guy) public view returns (uint);
            
                function approve(address guy, uint wad) public returns (bool);
                function transfer(address dst, uint wad) public returns (bool);
                function transferFrom(
                    address src, address dst, uint wad
                ) public returns (bool);
            }
            
            ////// src/base.sol
            /// base.sol -- basic ERC20 implementation
            
            // Copyright (C) 2015, 2016, 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.13; */
            
            /* import "erc20/erc20.sol"; */
            /* import "ds-math/math.sol"; */
            
            contract DSTokenBase is ERC20, DSMath {
                uint256                                            _supply;
                mapping (address => uint256)                       _balances;
                mapping (address => mapping (address => uint256))  _approvals;
            
                function DSTokenBase(uint supply) public {
                    _balances[msg.sender] = supply;
                    _supply = supply;
                }
            
                function totalSupply() public view returns (uint) {
                    return _supply;
                }
                function balanceOf(address src) public view returns (uint) {
                    return _balances[src];
                }
                function allowance(address src, address guy) public view returns (uint) {
                    return _approvals[src][guy];
                }
            
                function transfer(address dst, uint wad) public returns (bool) {
                    return transferFrom(msg.sender, dst, wad);
                }
            
                function transferFrom(address src, address dst, uint wad)
                    public
                    returns (bool)
                {
                    if (src != msg.sender) {
                        _approvals[src][msg.sender] = sub(_approvals[src][msg.sender], wad);
                    }
            
                    _balances[src] = sub(_balances[src], wad);
                    _balances[dst] = add(_balances[dst], wad);
            
                    Transfer(src, dst, wad);
            
                    return true;
                }
            
                function approve(address guy, uint wad) public returns (bool) {
                    _approvals[msg.sender][guy] = wad;
            
                    Approval(msg.sender, guy, wad);
            
                    return true;
                }
            }
            
            ////// src/token.sol
            /// token.sol -- ERC20 implementation with minting and burning
            
            // Copyright (C) 2015, 2016, 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.13; */
            
            /* import "ds-stop/stop.sol"; */
            
            /* import "./base.sol"; */
            
            contract DSToken is DSTokenBase(0), DSStop {
            
                bytes32  public  symbol;
                uint256  public  decimals = 18; // standard token precision. override to customize
            
                function DSToken(bytes32 symbol_) public {
                    symbol = symbol_;
                }
            
                event Mint(address indexed guy, uint wad);
                event Burn(address indexed guy, uint wad);
            
                function approve(address guy) public stoppable returns (bool) {
                    return super.approve(guy, uint(-1));
                }
            
                function approve(address guy, uint wad) public stoppable returns (bool) {
                    return super.approve(guy, wad);
                }
            
                function transferFrom(address src, address dst, uint wad)
                    public
                    stoppable
                    returns (bool)
                {
                    if (src != msg.sender && _approvals[src][msg.sender] != uint(-1)) {
                        _approvals[src][msg.sender] = sub(_approvals[src][msg.sender], wad);
                    }
            
                    _balances[src] = sub(_balances[src], wad);
                    _balances[dst] = add(_balances[dst], wad);
            
                    Transfer(src, dst, wad);
            
                    return true;
                }
            
                function push(address dst, uint wad) public {
                    transferFrom(msg.sender, dst, wad);
                }
                function pull(address src, uint wad) public {
                    transferFrom(src, msg.sender, wad);
                }
                function move(address src, address dst, uint wad) public {
                    transferFrom(src, dst, wad);
                }
            
                function mint(uint wad) public {
                    mint(msg.sender, wad);
                }
                function burn(uint wad) public {
                    burn(msg.sender, wad);
                }
                function mint(address guy, uint wad) public auth stoppable {
                    _balances[guy] = add(_balances[guy], wad);
                    _supply = add(_supply, wad);
                    Mint(guy, wad);
                }
                function burn(address guy, uint wad) public auth stoppable {
                    if (guy != msg.sender && _approvals[guy][msg.sender] != uint(-1)) {
                        _approvals[guy][msg.sender] = sub(_approvals[guy][msg.sender], wad);
                    }
            
                    _balances[guy] = sub(_balances[guy], wad);
                    _supply = sub(_supply, wad);
                    Burn(guy, wad);
                }
            
                // Optional token name
                bytes32   public  name = "";
            
                function setName(bytes32 name_) public auth {
                    name = name_;
                }
            }

            File 3 of 9: ScdMcdMigration
            // hevm: flattened sources of /nix/store/nrmi9gk7q94ba1fbhq9bphlbpqd1y8hw-scd-mcd-migration-e730e63/src/ScdMcdMigration.sol
            pragma solidity =0.5.12;
            
            ////// /nix/store/nrmi9gk7q94ba1fbhq9bphlbpqd1y8hw-scd-mcd-migration-e730e63/src/Interfaces.sol
            /* pragma solidity 0.5.12; */
            
            contract GemLike {
                function allowance(address, address) public returns (uint);
                function approve(address, uint) public;
                function transfer(address, uint) public returns (bool);
                function transferFrom(address, address, uint) public returns (bool);
            }
            
            contract ValueLike {
                function peek() public returns (uint, bool);
            }
            
            contract SaiTubLike {
                function skr() public view returns (GemLike);
                function gem() public view returns (GemLike);
                function gov() public view returns (GemLike);
                function sai() public view returns (GemLike);
                function pep() public view returns (ValueLike);
                function vox() public view returns (VoxLike);
                function bid(uint) public view returns (uint);
                function ink(bytes32) public view returns (uint);
                function tag() public view returns (uint);
                function tab(bytes32) public returns (uint);
                function rap(bytes32) public returns (uint);
                function draw(bytes32, uint) public;
                function shut(bytes32) public;
                function exit(uint) public;
                function give(bytes32, address) public;
            }
            
            contract VoxLike {
                function par() public returns (uint);
            }
            
            contract JoinLike {
                function ilk() public returns (bytes32);
                function gem() public returns (GemLike);
                function dai() public returns (GemLike);
                function join(address, uint) public;
                function exit(address, uint) public;
            }
            contract VatLike {
                function ilks(bytes32) public view returns (uint, uint, uint, uint, uint);
                function hope(address) public;
                function frob(bytes32, address, address, address, int, int) public;
            }
            
            contract ManagerLike {
                function vat() public view returns (address);
                function urns(uint) public view returns (address);
                function open(bytes32, address) public returns (uint);
                function frob(uint, int, int) public;
                function give(uint, address) public;
                function move(uint, address, uint) public;
            }
            
            contract OtcLike {
                function getPayAmount(address, address, uint) public view returns (uint);
                function buyAllAmount(address, uint, address, uint) public;
            }
            
            ////// /nix/store/nrmi9gk7q94ba1fbhq9bphlbpqd1y8hw-scd-mcd-migration-e730e63/src/ScdMcdMigration.sol
            /* pragma solidity 0.5.12; */
            
            /* import { JoinLike, ManagerLike, SaiTubLike, VatLike } from "./Interfaces.sol"; */
            
            contract ScdMcdMigration {
                SaiTubLike                  public tub;
                VatLike                     public vat;
                ManagerLike                 public cdpManager;
                JoinLike                    public saiJoin;
                JoinLike                    public wethJoin;
                JoinLike                    public daiJoin;
            
                constructor(
                    address tub_,           // SCD tub contract address
                    address cdpManager_,    // MCD manager contract address
                    address saiJoin_,       // MCD SAI collateral adapter contract address
                    address wethJoin_,      // MCD ETH collateral adapter contract address
                    address daiJoin_        // MCD DAI adapter contract address
                ) public {
                    tub = SaiTubLike(tub_);
                    cdpManager = ManagerLike(cdpManager_);
                    vat = VatLike(cdpManager.vat());
                    saiJoin = JoinLike(saiJoin_);
                    wethJoin = JoinLike(wethJoin_);
                    daiJoin = JoinLike(daiJoin_);
            
                    require(wethJoin.gem() == tub.gem(), "non-matching-weth");
                    require(saiJoin.gem() == tub.sai(), "non-matching-sai");
            
                    tub.gov().approve(address(tub), uint(-1));
                    tub.skr().approve(address(tub), uint(-1));
                    tub.sai().approve(address(tub), uint(-1));
                    tub.sai().approve(address(saiJoin), uint(-1));
                    wethJoin.gem().approve(address(wethJoin), uint(-1));
                    daiJoin.dai().approve(address(daiJoin), uint(-1));
                    vat.hope(address(daiJoin));
                }
            
                function add(uint x, uint y) internal pure returns (uint z) {
                    require((z = x + y) >= x, "add-overflow");
                }
            
                function sub(uint x, uint y) internal pure returns (uint z) {
                    require((z = x - y) <= x, "sub-underflow");
                }
            
                function mul(uint x, uint y) internal pure returns (uint z) {
                    require(y == 0 || (z = x * y) / y == x, "mul-overflow");
                }
            
                function toInt(uint x) internal pure returns (int y) {
                    y = int(x);
                    require(y >= 0, "int-overflow");
                }
            
                // Function to swap SAI to DAI
                // This function is to be used by users that want to get new DAI in exchange of old one (aka SAI)
                // wad amount has to be <= the value pending to reach the debt ceiling (the minimum between general and ilk one)
                function swapSaiToDai(
                    uint wad
                ) external {
                    // Get wad amount of SAI from user's wallet:
                    saiJoin.gem().transferFrom(msg.sender, address(this), wad);
                    // Join the SAI wad amount to the `vat`:
                    saiJoin.join(address(this), wad);
                    // Lock the SAI wad amount to the CDP and generate the same wad amount of DAI
                    vat.frob(saiJoin.ilk(), address(this), address(this), address(this), toInt(wad), toInt(wad));
                    // Send DAI wad amount as a ERC20 token to the user's wallet
                    daiJoin.exit(msg.sender, wad);
                }
            
                // Function to swap DAI to SAI
                // This function is to be used by users that want to get SAI in exchange of DAI
                // wad amount has to be <= the amount of SAI locked (and DAI generated) in the migration contract SAI CDP
                function swapDaiToSai(
                    uint wad
                ) external {
                    // Get wad amount of DAI from user's wallet:
                    daiJoin.dai().transferFrom(msg.sender, address(this), wad);
                    // Join the DAI wad amount to the vat:
                    daiJoin.join(address(this), wad);
                    // Payback the DAI wad amount and unlocks the same value of SAI collateral
                    vat.frob(saiJoin.ilk(), address(this), address(this), address(this), -toInt(wad), -toInt(wad));
                    // Send SAI wad amount as a ERC20 token to the user's wallet
                    saiJoin.exit(msg.sender, wad);
                }
            
                // Function to migrate a SCD CDP to MCD one (needs to be used via a proxy so the code can be kept simpler). Check MigrationProxyActions.sol code for usage.
                // In order to use migrate function, SCD CDP debtAmt needs to be <= SAI previously deposited in the SAI CDP * (100% - Collateralization Ratio)
                function migrate(
                    bytes32 cup
                ) external returns (uint cdp) {
                    // Get values
                    uint debtAmt = tub.tab(cup);    // CDP SAI debt
                    uint pethAmt = tub.ink(cup);    // CDP locked collateral
                    uint ethAmt = tub.bid(pethAmt); // CDP locked collateral equiv in ETH
            
                    // Take SAI out from MCD SAI CDP. For this operation is necessary to have a very low collateralization ratio
                    // This is not actually a problem as this ilk will only be accessed by this migration contract,
                    // which will make sure to have the amounts balanced out at the end of the execution.
                    vat.frob(
                        bytes32(saiJoin.ilk()),
                        address(this),
                        address(this),
                        address(this),
                        -toInt(debtAmt),
                        0
                    );
                    saiJoin.exit(address(this), debtAmt); // SAI is exited as a token
            
                    // Shut SAI CDP and gets WETH back
                    tub.shut(cup);      // CDP is closed using the SAI just exited and the MKR previously sent by the user (via the proxy call)
                    tub.exit(pethAmt);  // Converts PETH to WETH
            
                    // Open future user's CDP in MCD
                    cdp = cdpManager.open(wethJoin.ilk(), address(this));
            
                    // Join WETH to Adapter
                    wethJoin.join(cdpManager.urns(cdp), ethAmt);
            
                    // Lock WETH in future user's CDP and generate debt to compensate the SAI used to paid the SCD CDP
                    (, uint rate,,,) = vat.ilks(wethJoin.ilk());
                    cdpManager.frob(
                        cdp,
                        toInt(ethAmt),
                        toInt(mul(debtAmt, 10 ** 27) / rate + 1) // To avoid rounding issues we add an extra wei of debt
                    );
                    // Move DAI generated to migration contract (to recover the used funds)
                    cdpManager.move(cdp, address(this), mul(debtAmt, 10 ** 27));
                    // Re-balance MCD SAI migration contract's CDP
                    vat.frob(
                        bytes32(saiJoin.ilk()),
                        address(this),
                        address(this),
                        address(this),
                        0,
                        -toInt(debtAmt)
                    );
            
                    // Set ownership of CDP to the user
                    cdpManager.give(cdp, msg.sender);
                }
            }

            File 4 of 9: 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 5 of 9: AuthGemJoin
            // hevm: flattened sources of /nix/store/k8y52yly1kzii65m0yw5pbidrq3jlajh-dss-deploy-001fb27/src/join.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/k8y52yly1kzii65m0yw5pbidrq3jlajh-dss-deploy-001fb27/src/join.sol
            /// 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; */
            
            /* import "dss/lib.sol"; */
            
            contract VatLike {
                function slip(bytes32,address,int) public;
            }
            
            // GemJoin2
            
            // For a token that does not return a bool on transfer or transferFrom (like OMG)
            // This is one way of doing it. Check the balances before and after calling a transfer
            
            contract GemLike2 {
                function decimals() public view returns (uint);
                function transfer(address,uint) public;
                function transferFrom(address,address,uint) public;
                function balanceOf(address) public view returns (uint);
                function allowance(address,address) public view returns (uint);
            }
            
            contract GemJoin2 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;
                GemLike2 public gem;
                uint     public dec;
                uint     public live;  // Access Flag
            
                constructor(address vat_, bytes32 ilk_, address gem_) public {
                    wards[msg.sender] = 1;
                    live = 1;
                    vat = VatLike(vat_);
                    ilk = ilk_;
                    gem = GemLike2(gem_);
                    dec = gem.decimals();
                }
            
                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, "GemJoin2/overflow");
                }
            
                function join(address urn, uint wad) public note {
                    require(live == 1, "GemJoin2/not-live");
                    require(wad <= 2 ** 255, "GemJoin2/overflow");
                    vat.slip(ilk, urn, int(wad));
                    uint256 prevBalance = gem.balanceOf(msg.sender);
            
                    require(prevBalance >= wad, "GemJoin2/no-funds");
                    require(gem.allowance(msg.sender, address(this)) >= wad, "GemJoin2/no-allowance");
            
                    (bool ok,) = address(gem).call(
                        abi.encodeWithSignature("transferFrom(address,address,uint256)", msg.sender, address(this), wad)
                    );
                    require(ok, "GemJoin2/failed-transfer");
            
                    require(prevBalance - wad == gem.balanceOf(msg.sender), "GemJoin2/failed-transfer");
                }
            
                function exit(address guy, uint wad) public note {
                    require(wad <= 2 ** 255, "GemJoin2/overflow");
                    vat.slip(ilk, msg.sender, -int(wad));
                    uint256 prevBalance = gem.balanceOf(address(this));
            
                    require(prevBalance >= wad, "GemJoin2/no-funds");
            
                    (bool ok,) = address(gem).call(
                        abi.encodeWithSignature("transfer(address,uint256)", guy, wad)
                    );
                    require(ok, "GemJoin2/failed-transfer");
            
                    require(prevBalance - wad == gem.balanceOf(address(this)), "GemJoin2/failed-transfer");
                }
            }
            
            // GemJoin3
            // For a token that has a lower precision than 18 and doesn't have decimals field in place (like DGD)
            
            contract GemLike3 {
                function transfer(address,uint) public returns (bool);
                function transferFrom(address,address,uint) public returns (bool);
            }
            
            contract GemJoin3 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;
                GemLike3 public gem;
                uint     public dec;
                uint     public live;  // Access Flag
            
                constructor(address vat_, bytes32 ilk_, address gem_, uint decimals) public {
                    require(decimals < 18, "GemJoin3/decimals-18-or-higher");
                    wards[msg.sender] = 1;
                    live = 1;
                    vat = VatLike(vat_);
                    ilk = ilk_;
                    gem = GemLike3(gem_);
                    dec = decimals;
                }
            
                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, "GemJoin3/overflow");
                }
            
                function join(address urn, uint wad) public note {
                    require(live == 1, "GemJoin3/not-live");
                    uint wad18 = mul(wad, 10 ** (18 - dec));
                    require(wad18 <= 2 ** 255, "GemJoin3/overflow");
                    vat.slip(ilk, urn, int(wad18));
                    require(gem.transferFrom(msg.sender, address(this), wad), "GemJoin3/failed-transfer");
                }
            
                function exit(address guy, uint wad) public note {
                    uint wad18 = mul(wad, 10 ** (18 - dec));
                    require(wad18 <= 2 ** 255, "GemJoin3/overflow");
                    vat.slip(ilk, msg.sender, -int(wad18));
                    require(gem.transfer(guy, wad), "GemJoin3/failed-transfer");
                }
            }
            
            /// GemJoin4
            
            // Copyright (C) 2019 Lorenzo Manacorda <[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/>.
            
            // For tokens that do not implement transferFrom (like GNT), meaning the usual adapter
            // approach won't work: the adapter cannot call transferFrom and therefore
            // has no way of knowing when users deposit gems into it.
            
            // To work around this, we introduce the concept of a bag, which is a trusted
            // (it's created by the adapter), personalized component (one for each user).
            
            // Users first have to create their bag with `GemJoin4.make`, then transfer
            // gem to it, and then call `GemJoin4.join`, which transfer the gems from the
            // bag to the adapter.
            
            contract GemLike4 {
                function decimals() public view returns (uint);
                function balanceOf(address) public returns (uint256);
                function transfer(address, uint256) public returns (bool);
            }
            
            contract GemBag {
                address  public ada;
                address  public lad;
                GemLike4 public gem;
            
                constructor(address lad_, address gem_) public {
                    ada = msg.sender;
                    lad = lad_;
                    gem = GemLike4(gem_);
                }
            
                function exit(address usr, uint256 wad) external {
                    require(msg.sender == ada || msg.sender == lad, "GemBag/invalid-caller");
                    require(gem.transfer(usr, wad), "GemBag/failed-transfer");
                }
            }
            
            contract GemJoin4 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;
                GemLike4 public gem;
                uint     public dec;
                uint     public live;  // Access Flag
            
                mapping(address => address) public bags;
            
                constructor(address vat_, bytes32 ilk_, address gem_) public {
                    wards[msg.sender] = 1;
                    live = 1;
                    vat = VatLike(vat_);
                    ilk = ilk_;
                    gem = GemLike4(gem_);
                    dec = gem.decimals();
                }
            
                function cage() external note auth {
                    live = 0;
                }
            
                // -- admin --
                function make() external returns (address bag) {
                    bag = make(msg.sender);
                }
            
                function make(address usr) public note returns (address bag) {
                    require(bags[usr] == address(0), "GemJoin4/bag-already-exists");
            
                    bag = address(new GemBag(address(usr), address(gem)));
                    bags[usr] = bag;
                }
            
                // -- gems --
                function join(address urn, uint256 wad) external note {
                    require(live == 1, "GemJoin4/not-live");
                    require(int256(wad) >= 0, "GemJoin4/negative-amount");
            
                    GemBag(bags[msg.sender]).exit(address(this), wad);
                    vat.slip(ilk, urn, int256(wad));
                }
            
                function exit(address usr, uint256 wad) external note {
                    require(int256(wad) >= 0, "GemJoin4/negative-amount");
            
                    vat.slip(ilk, msg.sender, -int256(wad));
                    require(gem.transfer(usr, wad), "GemJoin4/failed-transfer");
                }
            }
            
            // AuthGemJoin
            // For a token that needs restriction on the sources which are able to execute the join function (like SAI through Migration contract)
            
            contract GemLike {
                function decimals() public view returns (uint);
                function transfer(address,uint) public returns (bool);
                function transferFrom(address,address,uint) public returns (bool);
            }
            
            contract AuthGemJoin is LibNote {
                VatLike public vat;
                bytes32 public ilk;
                GemLike public gem;
                uint    public dec;
                uint    public live;  // Access Flag
            
                // --- Auth ---
                mapping (address => uint) public wards;
                function rely(address usr) public note auth { wards[usr] = 1; }
                function deny(address usr) public note auth { wards[usr] = 0; }
                modifier auth { require(wards[msg.sender] == 1, "AuthGemJoin/non-authed"); _; }
            
                constructor(address vat_, bytes32 ilk_, address gem_) public {
                    wards[msg.sender] = 1;
                    live = 1;
                    vat = VatLike(vat_);
                    ilk = ilk_;
                    gem = GemLike(gem_);
                    dec = gem.decimals();
                }
            
                function cage() external note auth {
                    live = 0;
                }
            
                function join(address usr, uint wad) public auth note {
                    require(live == 1, "AuthGemJoin/not-live");
                    require(int(wad) >= 0, "AuthGemJoin/overflow");
                    vat.slip(ilk, usr, int(wad));
                    require(gem.transferFrom(msg.sender, address(this), wad), "AuthGemJoin/failed-transfer");
                }
            
                function exit(address usr, uint wad) public note {
                    require(wad <= 2 ** 255, "AuthGemJoin/overflow");
                    vat.slip(ilk, msg.sender, -int(wad));
                    require(gem.transfer(usr, wad), "AuthGemJoin/failed-transfer");
                }
            }

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

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

            File 8 of 9: MigrationProxyActions
            // hevm: flattened sources of /nix/store/nrmi9gk7q94ba1fbhq9bphlbpqd1y8hw-scd-mcd-migration-e730e63/src/MigrationProxyActions.sol
            pragma solidity =0.5.12 >0.4.13;
            
            ////// /nix/store/nrmi9gk7q94ba1fbhq9bphlbpqd1y8hw-scd-mcd-migration-e730e63/src/Interfaces.sol
            /* pragma solidity 0.5.12; */
            
            contract GemLike {
                function allowance(address, address) public returns (uint);
                function approve(address, uint) public;
                function transfer(address, uint) public returns (bool);
                function transferFrom(address, address, uint) public returns (bool);
            }
            
            contract ValueLike {
                function peek() public returns (uint, bool);
            }
            
            contract SaiTubLike {
                function skr() public view returns (GemLike);
                function gem() public view returns (GemLike);
                function gov() public view returns (GemLike);
                function sai() public view returns (GemLike);
                function pep() public view returns (ValueLike);
                function vox() public view returns (VoxLike);
                function bid(uint) public view returns (uint);
                function ink(bytes32) public view returns (uint);
                function tag() public view returns (uint);
                function tab(bytes32) public returns (uint);
                function rap(bytes32) public returns (uint);
                function draw(bytes32, uint) public;
                function shut(bytes32) public;
                function exit(uint) public;
                function give(bytes32, address) public;
            }
            
            contract VoxLike {
                function par() public returns (uint);
            }
            
            contract JoinLike {
                function ilk() public returns (bytes32);
                function gem() public returns (GemLike);
                function dai() public returns (GemLike);
                function join(address, uint) public;
                function exit(address, uint) public;
            }
            contract VatLike {
                function ilks(bytes32) public view returns (uint, uint, uint, uint, uint);
                function hope(address) public;
                function frob(bytes32, address, address, address, int, int) public;
            }
            
            contract ManagerLike {
                function vat() public view returns (address);
                function urns(uint) public view returns (address);
                function open(bytes32, address) public returns (uint);
                function frob(uint, int, int) public;
                function give(uint, address) public;
                function move(uint, address, uint) public;
            }
            
            contract OtcLike {
                function getPayAmount(address, address, uint) public view returns (uint);
                function buyAllAmount(address, uint, address, uint) public;
            }
            
            ////// /nix/store/nrmi9gk7q94ba1fbhq9bphlbpqd1y8hw-scd-mcd-migration-e730e63/src/ScdMcdMigration.sol
            /* pragma solidity 0.5.12; */
            
            /* import { JoinLike, ManagerLike, SaiTubLike, VatLike } from "./Interfaces.sol"; */
            
            contract ScdMcdMigration {
                SaiTubLike                  public tub;
                VatLike                     public vat;
                ManagerLike                 public cdpManager;
                JoinLike                    public saiJoin;
                JoinLike                    public wethJoin;
                JoinLike                    public daiJoin;
            
                constructor(
                    address tub_,           // SCD tub contract address
                    address cdpManager_,    // MCD manager contract address
                    address saiJoin_,       // MCD SAI collateral adapter contract address
                    address wethJoin_,      // MCD ETH collateral adapter contract address
                    address daiJoin_        // MCD DAI adapter contract address
                ) public {
                    tub = SaiTubLike(tub_);
                    cdpManager = ManagerLike(cdpManager_);
                    vat = VatLike(cdpManager.vat());
                    saiJoin = JoinLike(saiJoin_);
                    wethJoin = JoinLike(wethJoin_);
                    daiJoin = JoinLike(daiJoin_);
            
                    require(wethJoin.gem() == tub.gem(), "non-matching-weth");
                    require(saiJoin.gem() == tub.sai(), "non-matching-sai");
            
                    tub.gov().approve(address(tub), uint(-1));
                    tub.skr().approve(address(tub), uint(-1));
                    tub.sai().approve(address(tub), uint(-1));
                    tub.sai().approve(address(saiJoin), uint(-1));
                    wethJoin.gem().approve(address(wethJoin), uint(-1));
                    daiJoin.dai().approve(address(daiJoin), uint(-1));
                    vat.hope(address(daiJoin));
                }
            
                function add(uint x, uint y) internal pure returns (uint z) {
                    require((z = x + y) >= x, "add-overflow");
                }
            
                function sub(uint x, uint y) internal pure returns (uint z) {
                    require((z = x - y) <= x, "sub-underflow");
                }
            
                function mul(uint x, uint y) internal pure returns (uint z) {
                    require(y == 0 || (z = x * y) / y == x, "mul-overflow");
                }
            
                function toInt(uint x) internal pure returns (int y) {
                    y = int(x);
                    require(y >= 0, "int-overflow");
                }
            
                // Function to swap SAI to DAI
                // This function is to be used by users that want to get new DAI in exchange of old one (aka SAI)
                // wad amount has to be <= the value pending to reach the debt ceiling (the minimum between general and ilk one)
                function swapSaiToDai(
                    uint wad
                ) external {
                    // Get wad amount of SAI from user's wallet:
                    saiJoin.gem().transferFrom(msg.sender, address(this), wad);
                    // Join the SAI wad amount to the `vat`:
                    saiJoin.join(address(this), wad);
                    // Lock the SAI wad amount to the CDP and generate the same wad amount of DAI
                    vat.frob(saiJoin.ilk(), address(this), address(this), address(this), toInt(wad), toInt(wad));
                    // Send DAI wad amount as a ERC20 token to the user's wallet
                    daiJoin.exit(msg.sender, wad);
                }
            
                // Function to swap DAI to SAI
                // This function is to be used by users that want to get SAI in exchange of DAI
                // wad amount has to be <= the amount of SAI locked (and DAI generated) in the migration contract SAI CDP
                function swapDaiToSai(
                    uint wad
                ) external {
                    // Get wad amount of DAI from user's wallet:
                    daiJoin.dai().transferFrom(msg.sender, address(this), wad);
                    // Join the DAI wad amount to the vat:
                    daiJoin.join(address(this), wad);
                    // Payback the DAI wad amount and unlocks the same value of SAI collateral
                    vat.frob(saiJoin.ilk(), address(this), address(this), address(this), -toInt(wad), -toInt(wad));
                    // Send SAI wad amount as a ERC20 token to the user's wallet
                    saiJoin.exit(msg.sender, wad);
                }
            
                // Function to migrate a SCD CDP to MCD one (needs to be used via a proxy so the code can be kept simpler). Check MigrationProxyActions.sol code for usage.
                // In order to use migrate function, SCD CDP debtAmt needs to be <= SAI previously deposited in the SAI CDP * (100% - Collateralization Ratio)
                function migrate(
                    bytes32 cup
                ) external returns (uint cdp) {
                    // Get values
                    uint debtAmt = tub.tab(cup);    // CDP SAI debt
                    uint pethAmt = tub.ink(cup);    // CDP locked collateral
                    uint ethAmt = tub.bid(pethAmt); // CDP locked collateral equiv in ETH
            
                    // Take SAI out from MCD SAI CDP. For this operation is necessary to have a very low collateralization ratio
                    // This is not actually a problem as this ilk will only be accessed by this migration contract,
                    // which will make sure to have the amounts balanced out at the end of the execution.
                    vat.frob(
                        bytes32(saiJoin.ilk()),
                        address(this),
                        address(this),
                        address(this),
                        -toInt(debtAmt),
                        0
                    );
                    saiJoin.exit(address(this), debtAmt); // SAI is exited as a token
            
                    // Shut SAI CDP and gets WETH back
                    tub.shut(cup);      // CDP is closed using the SAI just exited and the MKR previously sent by the user (via the proxy call)
                    tub.exit(pethAmt);  // Converts PETH to WETH
            
                    // Open future user's CDP in MCD
                    cdp = cdpManager.open(wethJoin.ilk(), address(this));
            
                    // Join WETH to Adapter
                    wethJoin.join(cdpManager.urns(cdp), ethAmt);
            
                    // Lock WETH in future user's CDP and generate debt to compensate the SAI used to paid the SCD CDP
                    (, uint rate,,,) = vat.ilks(wethJoin.ilk());
                    cdpManager.frob(
                        cdp,
                        toInt(ethAmt),
                        toInt(mul(debtAmt, 10 ** 27) / rate + 1) // To avoid rounding issues we add an extra wei of debt
                    );
                    // Move DAI generated to migration contract (to recover the used funds)
                    cdpManager.move(cdp, address(this), mul(debtAmt, 10 ** 27));
                    // Re-balance MCD SAI migration contract's CDP
                    vat.frob(
                        bytes32(saiJoin.ilk()),
                        address(this),
                        address(this),
                        address(this),
                        0,
                        -toInt(debtAmt)
                    );
            
                    // Set ownership of CDP to the user
                    cdpManager.give(cdp, msg.sender);
                }
            }
            
            ////// /nix/store/s6vv2mwc272ak68b4aibr7fhpa85ikw8-ds-math/dapp/ds-math/src/math.sol
            /// math.sol -- mixin for inline numerical wizardry
            
            // 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.13; */
            
            contract DSMath {
                function add(uint x, uint y) internal pure returns (uint z) {
                    require((z = x + y) >= x, "ds-math-add-overflow");
                }
                function sub(uint x, uint y) internal pure returns (uint z) {
                    require((z = x - y) <= x, "ds-math-sub-underflow");
                }
                function mul(uint x, uint y) internal pure returns (uint z) {
                    require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
                }
            
                function min(uint x, uint y) internal pure returns (uint z) {
                    return x <= y ? x : y;
                }
                function max(uint x, uint y) internal pure returns (uint z) {
                    return x >= y ? x : y;
                }
                function imin(int x, int y) internal pure returns (int z) {
                    return x <= y ? x : y;
                }
                function imax(int x, int y) internal pure returns (int z) {
                    return x >= y ? x : y;
                }
            
                uint constant WAD = 10 ** 18;
                uint constant RAY = 10 ** 27;
            
                function wmul(uint x, uint y) internal pure returns (uint z) {
                    z = add(mul(x, y), WAD / 2) / WAD;
                }
                function rmul(uint x, uint y) internal pure returns (uint z) {
                    z = add(mul(x, y), RAY / 2) / RAY;
                }
                function wdiv(uint x, uint y) internal pure returns (uint z) {
                    z = add(mul(x, WAD), y / 2) / y;
                }
                function rdiv(uint x, uint y) internal pure returns (uint z) {
                    z = add(mul(x, RAY), y / 2) / y;
                }
            
                // This famous algorithm is called "exponentiation by squaring"
                // and calculates x^n with x as fixed-point and n as regular unsigned.
                //
                // It's O(log n), instead of O(n) for naive repeated multiplication.
                //
                // These facts are why it works:
                //
                //  If n is even, then x^n = (x^2)^(n/2).
                //  If n is odd,  then x^n = x * x^(n-1),
                //   and applying the equation for even x gives
                //    x^n = x * (x^2)^((n-1) / 2).
                //
                //  Also, EVM division is flooring and
                //    floor[(n-1) / 2] = floor[n / 2].
                //
                function rpow(uint x, uint n) internal pure returns (uint z) {
                    z = n % 2 != 0 ? x : RAY;
            
                    for (n /= 2; n != 0; n /= 2) {
                        x = rmul(x, x);
            
                        if (n % 2 != 0) {
                            z = rmul(z, x);
                        }
                    }
                }
            }
            
            ////// /nix/store/nrmi9gk7q94ba1fbhq9bphlbpqd1y8hw-scd-mcd-migration-e730e63/src/MigrationProxyActions.sol
            /* pragma solidity 0.5.12; */
            
            /* import "ds-math/math.sol"; */
            
            /* import { GemLike, JoinLike, OtcLike, SaiTubLike } from "./Interfaces.sol"; */
            /* import { ScdMcdMigration } from "./ScdMcdMigration.sol"; */
            
            // This contract is intended to be executed via the Profile proxy of a user (DSProxy) which owns the SCD CDP
            contract MigrationProxyActions is DSMath {
                function swapSaiToDai(
                    address scdMcdMigration,            // Migration contract address
                    uint wad                            // Amount to swap
                ) external {
                    GemLike sai = SaiTubLike(ScdMcdMigration(scdMcdMigration).tub()).sai();
                    GemLike dai = JoinLike(ScdMcdMigration(scdMcdMigration).daiJoin()).dai();
                    sai.transferFrom(msg.sender, address(this), wad);
                    if (sai.allowance(address(this), scdMcdMigration) < wad) {
                        sai.approve(scdMcdMigration, wad);
                    }
                    ScdMcdMigration(scdMcdMigration).swapSaiToDai(wad);
                    dai.transfer(msg.sender, wad);
                }
            
                function swapDaiToSai(
                    address scdMcdMigration,            // Migration contract address
                    uint wad                            // Amount to swap
                ) external {
                    GemLike sai = SaiTubLike(ScdMcdMigration(scdMcdMigration).tub()).sai();
                    GemLike dai = JoinLike(ScdMcdMigration(scdMcdMigration).daiJoin()).dai();
                    dai.transferFrom(msg.sender, address(this), wad);
                    if (dai.allowance(address(this), scdMcdMigration) < wad) {
                        dai.approve(scdMcdMigration, wad);
                    }
                    ScdMcdMigration(scdMcdMigration).swapDaiToSai(wad);
                    sai.transfer(msg.sender, wad);
                }
            
                function migrate(
                    address scdMcdMigration,            // Migration contract address
                    bytes32 cup                         // SCD CDP Id to migrate
                ) external returns (uint cdp) {
                    SaiTubLike tub = ScdMcdMigration(scdMcdMigration).tub();
                    // Get necessary MKR fee and move it to the migration contract
                    (uint val, bool ok) = tub.pep().peek();
                    if (ok && val != 0) {
                        // Calculate necessary value of MKR to pay the govFee
                        uint govFee = wdiv(tub.rap(cup), val);
            
                        // Get MKR from the user's wallet and transfer to Migration contract
                        tub.gov().transferFrom(msg.sender, address(scdMcdMigration), govFee);
                    }
                    // Transfer ownership of SCD CDP to the migration contract
                    tub.give(cup, address(scdMcdMigration));
                    // Execute migrate function
                    cdp = ScdMcdMigration(scdMcdMigration).migrate(cup);
                }
            
                function migratePayFeeWithGem(
                    address scdMcdMigration,            // Migration contract address
                    bytes32 cup,                        // SCD CDP Id to migrate
                    address otc,                        // Otc address
                    address payGem,                     // Token address to be used for purchasing govFee MKR
                    uint maxPayAmt                      // Max amount of payGem to sell for govFee MKR needed
                ) external returns (uint cdp) {
                    SaiTubLike tub = ScdMcdMigration(scdMcdMigration).tub();
                    // Get necessary MKR fee and move it to the migration contract
                    (uint val, bool ok) = tub.pep().peek();
                    if (ok && val != 0) {
                        // Calculate necessary value of MKR to pay the govFee
                        uint govFee = wdiv(tub.rap(cup), val);
            
                        // Calculate how much payGem is needed for getting govFee value
                        uint payAmt = OtcLike(otc).getPayAmount(payGem, address(tub.gov()), govFee);
                        // Fails if exceeds maximum
                        require(maxPayAmt >= payAmt, "maxPayAmt-exceeded");
                        // Set allowance, if necessary
                        if (GemLike(payGem).allowance(address(this), otc) < payAmt) {
                            GemLike(payGem).approve(otc, payAmt);
                        }
                        // Get payAmt of payGem from user's wallet
                        require(GemLike(payGem).transferFrom(msg.sender, address(this), payAmt), "transfer-failed");
                        // Trade it for govFee amount of MKR
                        OtcLike(otc).buyAllAmount(address(tub.gov()), govFee, payGem, payAmt);
                        // Transfer govFee amount of MKR to Migration contract
                        tub.gov().transfer(address(scdMcdMigration), govFee);
                    }
                    // Transfer ownership of SCD CDP to the migration contract
                    tub.give(cup, address(scdMcdMigration));
                    // Execute migrate function
                    cdp = ScdMcdMigration(scdMcdMigration).migrate(cup);
                }
            
                function _getRatio(
                    SaiTubLike tub,
                    bytes32 cup
                ) internal returns (uint ratio) {
                    ratio = rdiv(
                                    rmul(tub.tag(), tub.ink(cup)),
                                    rmul(tub.vox().par(), tub.tab(cup))
                                );
                }
            
                function migratePayFeeWithDebt(
                    address scdMcdMigration,            // Migration contract address
                    bytes32 cup,                        // SCD CDP Id to migrate
                    address otc,                        // Otc address
                    uint maxPayAmt,                     // Max amount of SAI to generate to sell for govFee MKR needed
                    uint minRatio                       // Min collateralization ratio after generating new debt (e.g. 180% = 1.8 RAY)
                ) external returns (uint cdp) {
                    SaiTubLike tub = ScdMcdMigration(scdMcdMigration).tub();
                    // Get necessary MKR fee and move it to the migration contract
                    (uint val, bool ok) = tub.pep().peek();
                    if (ok && val != 0) {
                        // Calculate necessary value of MKR to pay the govFee
                        uint govFee = wdiv(tub.rap(cup), val) + 1; // 1 extra wei MKR to avoid any possible rounding issue after drawing new SAI
            
                        // Calculate how much SAI is needed for getting govFee value
                        uint payAmt = OtcLike(otc).getPayAmount(address(tub.sai()), address(tub.gov()), govFee);
                        // Fails if exceeds maximum
                        require(maxPayAmt >= payAmt, "maxPayAmt-exceeded");
                        // Get payAmt of SAI from user's CDP
                        tub.draw(cup, payAmt);
            
                        require(_getRatio(tub, cup) > minRatio, "minRatio-failed");
            
                        // Set allowance, if necessary
                        if (GemLike(address(tub.sai())).allowance(address(this), otc) < payAmt) {
                            GemLike(address(tub.sai())).approve(otc, payAmt);
                        }
                        // Trade it for govFee amount of MKR
                        OtcLike(otc).buyAllAmount(address(tub.gov()), govFee, address(tub.sai()), payAmt);
                        // Transfer real needed govFee amount of MKR to Migration contract (it might leave some MKR dust in the proxy contract)
                        govFee = wdiv(tub.rap(cup), val);
                        tub.gov().transfer(address(scdMcdMigration), govFee);
                    }
                    // Transfer ownership of SCD CDP to the migration contract
                    tub.give(cup, address(scdMcdMigration));
                    // Execute migrate function
                    cdp = ScdMcdMigration(scdMcdMigration).migrate(cup);
                }
            }

            File 9 of 9: SaiTub
            // hevm: flattened sources of src/tub.sol
            pragma solidity ^0.4.18;
            
            ////// lib/ds-guard/lib/ds-auth/src/auth.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.4.13; */
            
            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;
            
                function DSAuth() public {
                    owner = msg.sender;
                    LogSetOwner(msg.sender);
                }
            
                function setOwner(address owner_)
                    public
                    auth
                {
                    owner = owner_;
                    LogSetOwner(owner);
                }
            
                function setAuthority(DSAuthority authority_)
                    public
                    auth
                {
                    authority = authority_;
                    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);
                    }
                }
            }
            
            ////// lib/ds-spell/lib/ds-note/src/note.sol
            /// note.sol -- the `note' modifier, for logging calls as events
            
            // 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.13; */
            
            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)
                    }
            
                    LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
            
                    _;
                }
            }
            
            ////// lib/ds-thing/lib/ds-math/src/math.sol
            /// math.sol -- mixin for inline numerical wizardry
            
            // 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.13; */
            
            contract DSMath {
                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);
                }
            
                function min(uint x, uint y) internal pure returns (uint z) {
                    return x <= y ? x : y;
                }
                function max(uint x, uint y) internal pure returns (uint z) {
                    return x >= y ? x : y;
                }
                function imin(int x, int y) internal pure returns (int z) {
                    return x <= y ? x : y;
                }
                function imax(int x, int y) internal pure returns (int z) {
                    return x >= y ? x : y;
                }
            
                uint constant WAD = 10 ** 18;
                uint constant RAY = 10 ** 27;
            
                function wmul(uint x, uint y) internal pure returns (uint z) {
                    z = add(mul(x, y), WAD / 2) / WAD;
                }
                function rmul(uint x, uint y) internal pure returns (uint z) {
                    z = add(mul(x, y), RAY / 2) / RAY;
                }
                function wdiv(uint x, uint y) internal pure returns (uint z) {
                    z = add(mul(x, WAD), y / 2) / y;
                }
                function rdiv(uint x, uint y) internal pure returns (uint z) {
                    z = add(mul(x, RAY), y / 2) / y;
                }
            
                // This famous algorithm is called "exponentiation by squaring"
                // and calculates x^n with x as fixed-point and n as regular unsigned.
                //
                // It's O(log n), instead of O(n) for naive repeated multiplication.
                //
                // These facts are why it works:
                //
                //  If n is even, then x^n = (x^2)^(n/2).
                //  If n is odd,  then x^n = x * x^(n-1),
                //   and applying the equation for even x gives
                //    x^n = x * (x^2)^((n-1) / 2).
                //
                //  Also, EVM division is flooring and
                //    floor[(n-1) / 2] = floor[n / 2].
                //
                function rpow(uint x, uint n) internal pure returns (uint z) {
                    z = n % 2 != 0 ? x : RAY;
            
                    for (n /= 2; n != 0; n /= 2) {
                        x = rmul(x, x);
            
                        if (n % 2 != 0) {
                            z = rmul(z, x);
                        }
                    }
                }
            }
            
            ////// lib/ds-thing/src/thing.sol
            // thing.sol - `auth` with handy mixins. your things should be DSThings
            
            // 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.13; */
            
            /* import 'ds-auth/auth.sol'; */
            /* import 'ds-note/note.sol'; */
            /* import 'ds-math/math.sol'; */
            
            contract DSThing is DSAuth, DSNote, DSMath {
            
                function S(string s) internal pure returns (bytes4) {
                    return bytes4(keccak256(s));
                }
            
            }
            
            ////// lib/ds-token/lib/ds-stop/src/stop.sol
            /// stop.sol -- mixin for enable/disable functionality
            
            // 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.13; */
            
            /* import "ds-auth/auth.sol"; */
            /* import "ds-note/note.sol"; */
            
            contract DSStop is DSNote, DSAuth {
            
                bool public stopped;
            
                modifier stoppable {
                    require(!stopped);
                    _;
                }
                function stop() public auth note {
                    stopped = true;
                }
                function start() public auth note {
                    stopped = false;
                }
            
            }
            
            ////// lib/ds-token/lib/erc20/src/erc20.sol
            /// erc20.sol -- API for the ERC20 token standard
            
            // See <https://github.com/ethereum/EIPs/issues/20>.
            
            // This file likely does not meet the threshold of originality
            // required for copyright to apply.  As a result, this is free and
            // unencumbered software belonging to the public domain.
            
            /* pragma solidity ^0.4.8; */
            
            contract ERC20Events {
                event Approval(address indexed src, address indexed guy, uint wad);
                event Transfer(address indexed src, address indexed dst, uint wad);
            }
            
            contract ERC20 is ERC20Events {
                function totalSupply() public view returns (uint);
                function balanceOf(address guy) public view returns (uint);
                function allowance(address src, address guy) public view returns (uint);
            
                function approve(address guy, uint wad) public returns (bool);
                function transfer(address dst, uint wad) public returns (bool);
                function transferFrom(
                    address src, address dst, uint wad
                ) public returns (bool);
            }
            
            ////// lib/ds-token/src/base.sol
            /// base.sol -- basic ERC20 implementation
            
            // Copyright (C) 2015, 2016, 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.13; */
            
            /* import "erc20/erc20.sol"; */
            /* import "ds-math/math.sol"; */
            
            contract DSTokenBase is ERC20, DSMath {
                uint256                                            _supply;
                mapping (address => uint256)                       _balances;
                mapping (address => mapping (address => uint256))  _approvals;
            
                function DSTokenBase(uint supply) public {
                    _balances[msg.sender] = supply;
                    _supply = supply;
                }
            
                function totalSupply() public view returns (uint) {
                    return _supply;
                }
                function balanceOf(address src) public view returns (uint) {
                    return _balances[src];
                }
                function allowance(address src, address guy) public view returns (uint) {
                    return _approvals[src][guy];
                }
            
                function transfer(address dst, uint wad) public returns (bool) {
                    return transferFrom(msg.sender, dst, wad);
                }
            
                function transferFrom(address src, address dst, uint wad)
                    public
                    returns (bool)
                {
                    if (src != msg.sender) {
                        _approvals[src][msg.sender] = sub(_approvals[src][msg.sender], wad);
                    }
            
                    _balances[src] = sub(_balances[src], wad);
                    _balances[dst] = add(_balances[dst], wad);
            
                    Transfer(src, dst, wad);
            
                    return true;
                }
            
                function approve(address guy, uint wad) public returns (bool) {
                    _approvals[msg.sender][guy] = wad;
            
                    Approval(msg.sender, guy, wad);
            
                    return true;
                }
            }
            
            ////// lib/ds-token/src/token.sol
            /// token.sol -- ERC20 implementation with minting and burning
            
            // Copyright (C) 2015, 2016, 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.13; */
            
            /* import "ds-stop/stop.sol"; */
            
            /* import "./base.sol"; */
            
            contract DSToken is DSTokenBase(0), DSStop {
            
                bytes32  public  symbol;
                uint256  public  decimals = 18; // standard token precision. override to customize
            
                function DSToken(bytes32 symbol_) public {
                    symbol = symbol_;
                }
            
                event Mint(address indexed guy, uint wad);
                event Burn(address indexed guy, uint wad);
            
                function approve(address guy) public stoppable returns (bool) {
                    return super.approve(guy, uint(-1));
                }
            
                function approve(address guy, uint wad) public stoppable returns (bool) {
                    return super.approve(guy, wad);
                }
            
                function transferFrom(address src, address dst, uint wad)
                    public
                    stoppable
                    returns (bool)
                {
                    if (src != msg.sender && _approvals[src][msg.sender] != uint(-1)) {
                        _approvals[src][msg.sender] = sub(_approvals[src][msg.sender], wad);
                    }
            
                    _balances[src] = sub(_balances[src], wad);
                    _balances[dst] = add(_balances[dst], wad);
            
                    Transfer(src, dst, wad);
            
                    return true;
                }
            
                function push(address dst, uint wad) public {
                    transferFrom(msg.sender, dst, wad);
                }
                function pull(address src, uint wad) public {
                    transferFrom(src, msg.sender, wad);
                }
                function move(address src, address dst, uint wad) public {
                    transferFrom(src, dst, wad);
                }
            
                function mint(uint wad) public {
                    mint(msg.sender, wad);
                }
                function burn(uint wad) public {
                    burn(msg.sender, wad);
                }
                function mint(address guy, uint wad) public auth stoppable {
                    _balances[guy] = add(_balances[guy], wad);
                    _supply = add(_supply, wad);
                    Mint(guy, wad);
                }
                function burn(address guy, uint wad) public auth stoppable {
                    if (guy != msg.sender && _approvals[guy][msg.sender] != uint(-1)) {
                        _approvals[guy][msg.sender] = sub(_approvals[guy][msg.sender], wad);
                    }
            
                    _balances[guy] = sub(_balances[guy], wad);
                    _supply = sub(_supply, wad);
                    Burn(guy, wad);
                }
            
                // Optional token name
                bytes32   public  name = "";
            
                function setName(bytes32 name_) public auth {
                    name = name_;
                }
            }
            
            ////// lib/ds-value/src/value.sol
            /// value.sol - a value is a simple thing, it can be get and set
            
            // 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.13; */
            
            /* import 'ds-thing/thing.sol'; */
            
            contract DSValue is DSThing {
                bool    has;
                bytes32 val;
                function peek() public view returns (bytes32, bool) {
                    return (val,has);
                }
                function read() public view returns (bytes32) {
                    var (wut, haz) = peek();
                    assert(haz);
                    return wut;
                }
                function poke(bytes32 wut) public note auth {
                    val = wut;
                    has = true;
                }
                function void() public note auth {  // unset the value
                    has = false;
                }
            }
            
            ////// src/vox.sol
            /// vox.sol -- target price feed
            
            // Copyright (C) 2016, 2017  Nikolai Mushegian <[email protected]>
            // Copyright (C) 2016, 2017  Daniel Brockman <[email protected]>
            // Copyright (C) 2017        Rain Break <[email protected]>
            
            // 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.18; */
            
            /* import "ds-thing/thing.sol"; */
            
            contract SaiVox is DSThing {
                uint256  _par;
                uint256  _way;
            
                uint256  public  fix;
                uint256  public  how;
                uint256  public  tau;
            
                function SaiVox(uint par_) public {
                    _par = fix = par_;
                    _way = RAY;
                    tau  = era();
                }
            
                function era() public view returns (uint) {
                    return block.timestamp;
                }
            
                function mold(bytes32 param, uint val) public note auth {
                    if (param == 'way') _way = val;
                }
            
                // Dai Target Price (ref per dai)
                function par() public returns (uint) {
                    prod();
                    return _par;
                }
                function way() public returns (uint) {
                    prod();
                    return _way;
                }
            
                function tell(uint256 ray) public note auth {
                    fix = ray;
                }
                function tune(uint256 ray) public note auth {
                    how = ray;
                }
            
                function prod() public note {
                    var age = era() - tau;
                    if (age == 0) return;  // optimised
                    tau = era();
            
                    if (_way != RAY) _par = rmul(_par, rpow(_way, age));  // optimised
            
                    if (how == 0) return;  // optimised
                    var wag = int128(how * age);
                    _way = inj(prj(_way) + (fix < _par ? wag : -wag));
                }
            
                function inj(int128 x) internal pure returns (uint256) {
                    return x >= 0 ? uint256(x) + RAY
                        : rdiv(RAY, RAY + uint256(-x));
                }
                function prj(uint256 x) internal pure returns (int128) {
                    return x >= RAY ? int128(x - RAY)
                        : int128(RAY) - int128(rdiv(RAY, x));
                }
            }
            
            ////// src/tub.sol
            /// tub.sol -- simplified CDP engine (baby brother of `vat')
            
            // Copyright (C) 2017  Nikolai Mushegian <[email protected]>
            // Copyright (C) 2017  Daniel Brockman <[email protected]>
            // Copyright (C) 2017  Rain Break <[email protected]>
            
            // 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.18; */
            
            /* import "ds-thing/thing.sol"; */
            /* import "ds-token/token.sol"; */
            /* import "ds-value/value.sol"; */
            
            /* import "./vox.sol"; */
            
            contract SaiTubEvents {
                event LogNewCup(address indexed lad, bytes32 cup);
            }
            
            contract SaiTub is DSThing, SaiTubEvents {
                DSToken  public  sai;  // Stablecoin
                DSToken  public  sin;  // Debt (negative sai)
            
                DSToken  public  skr;  // Abstracted collateral
                ERC20    public  gem;  // Underlying collateral
            
                DSToken  public  gov;  // Governance token
            
                SaiVox   public  vox;  // Target price feed
                DSValue  public  pip;  // Reference price feed
                DSValue  public  pep;  // Governance price feed
            
                address  public  tap;  // Liquidator
                address  public  pit;  // Governance Vault
            
                uint256  public  axe;  // Liquidation penalty
                uint256  public  cap;  // Debt ceiling
                uint256  public  mat;  // Liquidation ratio
                uint256  public  tax;  // Stability fee
                uint256  public  fee;  // Governance fee
                uint256  public  gap;  // Join-Exit Spread
            
                bool     public  off;  // Cage flag
                bool     public  out;  // Post cage exit
            
                uint256  public  fit;  // REF per SKR (just before settlement)
            
                uint256  public  rho;  // Time of last drip
                uint256         _chi;  // Accumulated Tax Rates
                uint256         _rhi;  // Accumulated Tax + Fee Rates
                uint256  public  rum;  // Total normalised debt
            
                uint256                   public  cupi;
                mapping (bytes32 => Cup)  public  cups;
            
                struct Cup {
                    address  lad;      // CDP owner
                    uint256  ink;      // Locked collateral (in SKR)
                    uint256  art;      // Outstanding normalised debt (tax only)
                    uint256  ire;      // Outstanding normalised debt
                }
            
                function lad(bytes32 cup) public view returns (address) {
                    return cups[cup].lad;
                }
                function ink(bytes32 cup) public view returns (uint) {
                    return cups[cup].ink;
                }
                function tab(bytes32 cup) public returns (uint) {
                    return rmul(cups[cup].art, chi());
                }
                function rap(bytes32 cup) public returns (uint) {
                    return sub(rmul(cups[cup].ire, rhi()), tab(cup));
                }
            
                // Total CDP Debt
                function din() public returns (uint) {
                    return rmul(rum, chi());
                }
                // Backing collateral
                function air() public view returns (uint) {
                    return skr.balanceOf(this);
                }
                // Raw collateral
                function pie() public view returns (uint) {
                    return gem.balanceOf(this);
                }
            
                //------------------------------------------------------------------
            
                function SaiTub(
                    DSToken  sai_,
                    DSToken  sin_,
                    DSToken  skr_,
                    ERC20    gem_,
                    DSToken  gov_,
                    DSValue  pip_,
                    DSValue  pep_,
                    SaiVox   vox_,
                    address  pit_
                ) public {
                    gem = gem_;
                    skr = skr_;
            
                    sai = sai_;
                    sin = sin_;
            
                    gov = gov_;
                    pit = pit_;
            
                    pip = pip_;
                    pep = pep_;
                    vox = vox_;
            
                    axe = RAY;
                    mat = RAY;
                    tax = RAY;
                    fee = RAY;
                    gap = WAD;
            
                    _chi = RAY;
                    _rhi = RAY;
            
                    rho = era();
                }
            
                function era() public constant returns (uint) {
                    return block.timestamp;
                }
            
                //--Risk-parameter-config-------------------------------------------
            
                function mold(bytes32 param, uint val) public note auth {
                    if      (param == 'cap') cap = val;
                    else if (param == 'mat') { require(val >= RAY); mat = val; }
                    else if (param == 'tax') { require(val >= RAY); drip(); tax = val; }
                    else if (param == 'fee') { require(val >= RAY); drip(); fee = val; }
                    else if (param == 'axe') { require(val >= RAY); axe = val; }
                    else if (param == 'gap') { require(val >= WAD); gap = val; }
                    else return;
                }
            
                //--Price-feed-setters----------------------------------------------
            
                function setPip(DSValue pip_) public note auth {
                    pip = pip_;
                }
                function setPep(DSValue pep_) public note auth {
                    pep = pep_;
                }
                function setVox(SaiVox vox_) public note auth {
                    vox = vox_;
                }
            
                //--Tap-setter------------------------------------------------------
                function turn(address tap_) public note {
                    require(tap  == 0);
                    require(tap_ != 0);
                    tap = tap_;
                }
            
                //--Collateral-wrapper----------------------------------------------
            
                // Wrapper ratio (gem per skr)
                function per() public view returns (uint ray) {
                    return skr.totalSupply() == 0 ? RAY : rdiv(pie(), skr.totalSupply());
                }
                // Join price (gem per skr)
                function ask(uint wad) public view returns (uint) {
                    return rmul(wad, wmul(per(), gap));
                }
                // Exit price (gem per skr)
                function bid(uint wad) public view returns (uint) {
                    return rmul(wad, wmul(per(), sub(2 * WAD, gap)));
                }
                function join(uint wad) public note {
                    require(!off);
                    require(ask(wad) > 0);
                    require(gem.transferFrom(msg.sender, this, ask(wad)));
                    skr.mint(msg.sender, wad);
                }
                function exit(uint wad) public note {
                    require(!off || out);
                    require(gem.transfer(msg.sender, bid(wad)));
                    skr.burn(msg.sender, wad);
                }
            
                //--Stability-fee-accumulation--------------------------------------
            
                // Accumulated Rates
                function chi() public returns (uint) {
                    drip();
                    return _chi;
                }
                function rhi() public returns (uint) {
                    drip();
                    return _rhi;
                }
                function drip() public note {
                    if (off) return;
            
                    var rho_ = era();
                    var age = rho_ - rho;
                    if (age == 0) return;    // optimised
                    rho = rho_;
            
                    var inc = RAY;
            
                    if (tax != RAY) {  // optimised
                        var _chi_ = _chi;
                        inc = rpow(tax, age);
                        _chi = rmul(_chi, inc);
                        sai.mint(tap, rmul(sub(_chi, _chi_), rum));
                    }
            
                    // optimised
                    if (fee != RAY) inc = rmul(inc, rpow(fee, age));
                    if (inc != RAY) _rhi = rmul(_rhi, inc);
                }
            
            
                //--CDP-risk-indicator----------------------------------------------
            
                // Abstracted collateral price (ref per skr)
                function tag() public view returns (uint wad) {
                    return off ? fit : wmul(per(), uint(pip.read()));
                }
                // Returns true if cup is well-collateralized
                function safe(bytes32 cup) public returns (bool) {
                    var pro = rmul(tag(), ink(cup));
                    var con = rmul(vox.par(), tab(cup));
                    var min = rmul(con, mat);
                    return pro >= min;
                }
            
            
                //--CDP-operations--------------------------------------------------
            
                function open() public note returns (bytes32 cup) {
                    require(!off);
                    cupi = add(cupi, 1);
                    cup = bytes32(cupi);
                    cups[cup].lad = msg.sender;
                    LogNewCup(msg.sender, cup);
                }
                function give(bytes32 cup, address guy) public note {
                    require(msg.sender == cups[cup].lad);
                    require(guy != 0);
                    cups[cup].lad = guy;
                }
            
                function lock(bytes32 cup, uint wad) public note {
                    require(!off);
                    cups[cup].ink = add(cups[cup].ink, wad);
                    skr.pull(msg.sender, wad);
                    require(cups[cup].ink == 0 || cups[cup].ink > 0.005 ether);
                }
                function free(bytes32 cup, uint wad) public note {
                    require(msg.sender == cups[cup].lad);
                    cups[cup].ink = sub(cups[cup].ink, wad);
                    skr.push(msg.sender, wad);
                    require(safe(cup));
                    require(cups[cup].ink == 0 || cups[cup].ink > 0.005 ether);
                }
            
                function draw(bytes32 cup, uint wad) public note {
                    require(!off);
                    require(msg.sender == cups[cup].lad);
                    require(rdiv(wad, chi()) > 0);
            
                    cups[cup].art = add(cups[cup].art, rdiv(wad, chi()));
                    rum = add(rum, rdiv(wad, chi()));
            
                    cups[cup].ire = add(cups[cup].ire, rdiv(wad, rhi()));
                    sai.mint(cups[cup].lad, wad);
            
                    require(safe(cup));
                    require(sai.totalSupply() <= cap);
                }
                function wipe(bytes32 cup, uint wad) public note {
                    require(!off);
            
                    var owe = rmul(wad, rdiv(rap(cup), tab(cup)));
            
                    cups[cup].art = sub(cups[cup].art, rdiv(wad, chi()));
                    rum = sub(rum, rdiv(wad, chi()));
            
                    cups[cup].ire = sub(cups[cup].ire, rdiv(add(wad, owe), rhi()));
                    sai.burn(msg.sender, wad);
            
                    var (val, ok) = pep.peek();
                    if (ok && val != 0) gov.move(msg.sender, pit, wdiv(owe, uint(val)));
                }
            
                function shut(bytes32 cup) public note {
                    require(!off);
                    require(msg.sender == cups[cup].lad);
                    if (tab(cup) != 0) wipe(cup, tab(cup));
                    if (ink(cup) != 0) free(cup, ink(cup));
                    delete cups[cup];
                }
            
                function bite(bytes32 cup) public note {
                    require(!safe(cup) || off);
            
                    // Take on all of the debt, except unpaid fees
                    var rue = tab(cup);
                    sin.mint(tap, rue);
                    rum = sub(rum, cups[cup].art);
                    cups[cup].art = 0;
                    cups[cup].ire = 0;
            
                    // Amount owed in SKR, including liquidation penalty
                    var owe = rdiv(rmul(rmul(rue, axe), vox.par()), tag());
            
                    if (owe > cups[cup].ink) {
                        owe = cups[cup].ink;
                    }
            
                    skr.push(tap, owe);
                    cups[cup].ink = sub(cups[cup].ink, owe);
                }
            
                //------------------------------------------------------------------
            
                function cage(uint fit_, uint jam) public note auth {
                    require(!off && fit_ != 0);
                    off = true;
                    axe = RAY;
                    gap = WAD;
                    fit = fit_;         // ref per skr
                    require(gem.transfer(tap, jam));
                }
                function flow() public note auth {
                    require(off);
                    out = true;
                }
            }