ETH Price: $2,289.00 (-5.59%)

Transaction Decoder

Block:
9172368 at Dec-27-2019 08:17:54 PM +UTC
Transaction Fee:
0.002122476 ETH $4.86
Gas Used:
176,873 Gas / 12 Gwei

Emitted Events:

4 DSProxy.0x1cff79cd00000000000000000000000000000000000000000000000000000000( 0x1cff79cd00000000000000000000000000000000000000000000000000000000, 0x00000000000000000000000085b7bb9e585e07db90a8a8ae897ad23f7fff877f, 0x000000000000000000000000a483cfe6403949bf38c74f8c340651fb02246d21, 0x0000000000000000000000000000000000000000000000000000000000000040, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000004000000000, 000000000000000000000000000000000000000000000000000000e41cff79cd, 000000000000000000000000a483cfe6403949bf38c74f8c340651fb02246d21, 0000000000000000000000000000000000000000000000000000000000000040, 0000000000000000000000000000000000000000000000000000000000000064, 036a23950000000000000000000000005ef30b9986345249bc32d8928b7ee64d, e9435e390000000000000000000000009759a6ac90977b93b58547b4a71c7831, 7f391a2800000000000000000000000000000000000000000000000000000000, 0000038500000000000000000000000000000000000000000000000000000000 )
5 Dai.Transfer( src=[Sender] 0x85b7bb9e585e07db90a8a8ae897ad23f7fff877f, dst=[Receiver] DSProxy, wad=438889564584850797498 )
6 Dai.Approval( src=[Receiver] DSProxy, guy=DaiJoin, wad=438889564584850797498 )
7 Vat.0xbb35783b00000000000000000000000000000000000000000000000000000000( 0xbb35783b00000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000009759a6ac90977b93b58547b4a71c78317f391a28, 0x000000000000000000000000176fea7af8e2b89913025ecc30cda2339b66ea97, 0x0000000000000000000000004ce07d1d82c7fc473130b3cfec4e627890000000, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, bb35783b0000000000000000000000009759a6ac90977b93b58547b4a71c7831, 7f391a28000000000000000000000000176fea7af8e2b89913025ecc30cda233, 9b66ea970000000000000000000000004ce07d1d82c7fc473130b3cfec4e6278, 9000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
8 Dai.Transfer( src=[Receiver] DSProxy, dst=0x0000000000000000000000000000000000000000, wad=438889564584850797498 )
9 DaiJoin.0x3b4da69f00000000000000000000000000000000000000000000000000000000( 0x3b4da69f00000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000234ae13d6493e1b944150b9e899cc7b78a62e2dd, 0x000000000000000000000000176fea7af8e2b89913025ecc30cda2339b66ea97, 0x000000000000000000000000000000000000000000000017cad0f5a741e4b3ba, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 3b4da69f000000000000000000000000176fea7af8e2b89913025ecc30cda233, 9b66ea97000000000000000000000000000000000000000000000017cad0f5a7, 41e4b3ba00000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
10 Vat.0x7608870300000000000000000000000000000000000000000000000000000000( 0x7608870300000000000000000000000000000000000000000000000000000000, 0x4554482d41000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000176fea7af8e2b89913025ecc30cda2339b66ea97, 0x000000000000000000000000176fea7af8e2b89913025ecc30cda2339b66ea97, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 760887034554482d410000000000000000000000000000000000000000000000, 00000000000000000000000000000000176fea7af8e2b89913025ecc30cda233, 9b66ea97000000000000000000000000176fea7af8e2b89913025ecc30cda233, 9b66ea97000000000000000000000000176fea7af8e2b89913025ecc30cda233, 9b66ea9700000000000000000000000000000000000000000000000000000000, 00000000ffffffffffffffffffffffffffffffffffffffffffffffe851ea9bda, f65295ea00000000000000000000000000000000000000000000000000000000 )
11 DssCdpManager.0x45e6bdcd00000000000000000000000000000000000000000000000000000000( 0x45e6bdcd00000000000000000000000000000000000000000000000000000000, 0x000000000000000000000000234ae13d6493e1b944150b9e899cc7b78a62e2dd, 0x0000000000000000000000000000000000000000000000000000000000000385, 0x0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000020, 00000000000000000000000000000000000000000000000000000000000000e0, 45e6bdcd00000000000000000000000000000000000000000000000000000000, 0000038500000000000000000000000000000000000000000000000000000000, 00000000ffffffffffffffffffffffffffffffffffffffffffffffe851ea9bda, f65295ea00000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000000 )
12 DSProxy.0xe4275ad86602c8a988ebb068f79af14314fce39b7863b231e4883d5726b61c55( 0xe4275ad86602c8a988ebb068f79af14314fce39b7863b231e4883d5726b61c55, 0x82858c5b7a45973445628610811bd3be25eb7ab03d4296804d10ca3dae85593d, 0x0000000000000000000000000000000000000000000000000000000000000385, 0000000000000000000000000000000000000000000000000000000000000000, 000000000000000000000000000000000000000000000017ae15642509ad6a16 )

Account State Difference:

  Address   Before After State Difference Code
0x35D1b3F3...259A0492B
(Sky: MCD Vat)
0x6B175474...495271d0F
0x85b7bB9e...F7FFf877F
0.057860255977566182 Eth
Nonce: 110
0.055737779977566182 Eth
Nonce: 111
0.002122476
(Ethermine)
338.362724496572494084 Eth338.364846972572494084 Eth0.002122476

Execution Trace

DSProxy.execute( _target=0xa483CFE6403949bf38c74F8C340651fb02246d21, _data=0x036A23950000000000000000000000005EF30B9986345249BC32D8928B7EE64DE9435E390000000000000000000000009759A6AC90977B93B58547B4A71C78317F391A280000000000000000000000000000000000000000000000000000000000000385 ) => ( response=0000000000000000000000000000000000000000000000000000000000000000 )
  • SaverProxyActions.wipeAll( manager=0x5ef30b9986345249bc32d8928B7ee64DE9435E39, daiJoin=0x9759A6Ac90977b93B58547b4A71c78317f391A28, cdp=901 )
    • DssCdpManager.STATICCALL( )
    • DssCdpManager.urns( 901 ) => ( 0x176feA7af8e2B89913025eCC30Cda2339b66EA97 )
    • DssCdpManager.ilks( 901 ) => ( 4554482D41000000000000000000000000000000000000000000000000000000 )
    • Vat.urns( 4554482D41000000000000000000000000000000000000000000000000000000, 0x176feA7af8e2B89913025eCC30Cda2339b66EA97 ) => ( ink=6008408645031752760, art=436819156142668999190 )
    • DssCdpManager.owns( 901 ) => ( 0x234AE13D6493E1b944150b9e899CC7b78A62E2dD )
    • Vat.ilks( 4554482D41000000000000000000000000000000000000000000000000000000 ) => ( Art=67820864500533637000824138, rate=1004739738203023277215240818, spot=83976666666666666666666666666, line=75000000000000000000000000000000000000000000000000000, dust=20000000000000000000000000000000000000000000000 )
    • Vat.urns( 4554482D41000000000000000000000000000000000000000000000000000000, 0x176feA7af8e2B89913025eCC30Cda2339b66EA97 ) => ( ink=6008408645031752760, art=436819156142668999190 )
    • Vat.dai( 0x176feA7af8e2B89913025eCC30Cda2339b66EA97 ) => ( 219542620875858017771972282 )
    • DaiJoin.CALL( )
    • Dai.transferFrom( src=0x85b7bB9e585e07DB90a8A8ae897AD23F7FFf877F, dst=0x234AE13D6493E1b944150b9e899CC7b78A62E2dD, wad=438889564584850797498 ) => ( True )
    • DaiJoin.CALL( )
    • Dai.approve( usr=0x9759A6Ac90977b93B58547b4A71c78317f391A28, wad=438889564584850797498 ) => ( True )
    • DaiJoin.join( usr=0x176feA7af8e2B89913025eCC30Cda2339b66EA97, wad=438889564584850797498 )
      • Vat.move( src=0x9759A6Ac90977b93B58547b4A71c78317f391A28, dst=0x176feA7af8e2B89913025eCC30Cda2339b66EA97, rad=438889564584850797498000000000000000000000000000 )
      • Dai.burn( usr=0x234AE13D6493E1b944150b9e899CC7b78A62E2dD, wad=438889564584850797498 )
      • DssCdpManager.frob( cdp=901, dink=0, dart=-436819156142668999190 )
        • Vat.frob( i=4554482D41000000000000000000000000000000000000000000000000000000, u=0x176feA7af8e2B89913025eCC30Cda2339b66EA97, v=0x176feA7af8e2B89913025eCC30Cda2339b66EA97, w=0x176feA7af8e2B89913025eCC30Cda2339b66EA97, dink=0, dart=-436819156142668999190 )
          File 1 of 6: DSProxy
          // proxy.sol - execute actions atomically through the proxy's identity
          
          // Copyright (C) 2017  DappHub, LLC
          
          // This program is free software: you can redistribute it and/or modify
          // it under the terms of the GNU General Public License as published by
          // the Free Software Foundation, either version 3 of the License, or
          // (at your option) any later version.
          
          // This program is distributed in the hope that it will be useful,
          // but WITHOUT ANY WARRANTY; without even the implied warranty of
          // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
          // GNU General Public License for more details.
          
          // You should have received a copy of the GNU General Public License
          // along with this program.  If not, see <http://www.gnu.org/licenses/>.
          
          pragma solidity ^0.4.23;
          
          contract DSAuthority {
              function canCall(
                  address src, address dst, bytes4 sig
              ) public view returns (bool);
          }
          
          contract DSAuthEvents {
              event LogSetAuthority (address indexed authority);
              event LogSetOwner     (address indexed owner);
          }
          
          contract DSAuth is DSAuthEvents {
              DSAuthority  public  authority;
              address      public  owner;
          
              constructor() public {
                  owner = msg.sender;
                  emit LogSetOwner(msg.sender);
              }
          
              function setOwner(address owner_)
                  public
                  auth
              {
                  owner = owner_;
                  emit LogSetOwner(owner);
              }
          
              function setAuthority(DSAuthority authority_)
                  public
                  auth
              {
                  authority = authority_;
                  emit LogSetAuthority(authority);
              }
          
              modifier auth {
                  require(isAuthorized(msg.sender, msg.sig));
                  _;
              }
          
              function isAuthorized(address src, bytes4 sig) internal view returns (bool) {
                  if (src == address(this)) {
                      return true;
                  } else if (src == owner) {
                      return true;
                  } else if (authority == DSAuthority(0)) {
                      return false;
                  } else {
                      return authority.canCall(src, this, sig);
                  }
              }
          }
          
          contract DSNote {
              event LogNote(
                  bytes4   indexed  sig,
                  address  indexed  guy,
                  bytes32  indexed  foo,
                  bytes32  indexed  bar,
                  uint              wad,
                  bytes             fax
              ) anonymous;
          
              modifier note {
                  bytes32 foo;
                  bytes32 bar;
          
                  assembly {
                      foo := calldataload(4)
                      bar := calldataload(36)
                  }
          
                  emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);
          
                  _;
              }
          }
          
          // DSProxy
          // Allows code execution using a persistant identity This can be very
          // useful to execute a sequence of atomic actions. Since the owner of
          // the proxy can be changed, this allows for dynamic ownership models
          // i.e. a multisig
          contract DSProxy is DSAuth, DSNote {
              DSProxyCache public cache;  // global cache for contracts
          
              constructor(address _cacheAddr) public {
                  require(setCache(_cacheAddr));
              }
          
              function() public payable {
              }
          
              // use the proxy to execute calldata _data on contract _code
              function execute(bytes _code, bytes _data)
                  public
                  payable
                  returns (address target, bytes32 response)
              {
                  target = cache.read(_code);
                  if (target == 0x0) {
                      // deploy contract & store its address in cache
                      target = cache.write(_code);
                  }
          
                  response = execute(target, _data);
              }
          
              function execute(address _target, bytes _data)
                  public
                  auth
                  note
                  payable
                  returns (bytes32 response)
              {
                  require(_target != 0x0);
          
                  // call contract in current context
                  assembly {
                      let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 32)
                      response := mload(0)      // load delegatecall output
                      switch iszero(succeeded)
                      case 1 {
                          // throw if delegatecall failed
                          revert(0, 0)
                      }
                  }
              }
          
              //set new cache
              function setCache(address _cacheAddr)
                  public
                  auth
                  note
                  returns (bool)
              {
                  require(_cacheAddr != 0x0);        // invalid cache address
                  cache = DSProxyCache(_cacheAddr);  // overwrite cache
                  return true;
              }
          }
          
          // DSProxyFactory
          // This factory deploys new proxy instances through build()
          // Deployed proxy addresses are logged
          contract DSProxyFactory {
              event Created(address indexed sender, address indexed owner, address proxy, address cache);
              mapping(address=>bool) public isProxy;
              DSProxyCache public cache = new DSProxyCache();
          
              // deploys a new proxy instance
              // sets owner of proxy to caller
              function build() public returns (DSProxy proxy) {
                  proxy = build(msg.sender);
              }
          
              // deploys a new proxy instance
              // sets custom owner of proxy
              function build(address owner) public returns (DSProxy proxy) {
                  proxy = new DSProxy(cache);
                  emit Created(msg.sender, owner, address(proxy), address(cache));
                  proxy.setOwner(owner);
                  isProxy[proxy] = true;
              }
          }
          
          // DSProxyCache
          // This global cache stores addresses of contracts previously deployed
          // by a proxy. This saves gas from repeat deployment of the same
          // contracts and eliminates blockchain bloat.
          
          // By default, all proxies deployed from the same factory store
          // contracts in the same cache. The cache a proxy instance uses can be
          // changed.  The cache uses the sha3 hash of a contract's bytecode to
          // lookup the address
          contract DSProxyCache {
              mapping(bytes32 => address) cache;
          
              function read(bytes _code) public view returns (address) {
                  bytes32 hash = keccak256(_code);
                  return cache[hash];
              }
          
              function write(bytes _code) public returns (address target) {
                  assembly {
                      target := create(0, add(_code, 0x20), mload(_code))
                      switch iszero(extcodesize(target))
                      case 1 {
                          // throw if contract failed to deploy
                          revert(0, 0)
                      }
                  }
                  bytes32 hash = keccak256(_code);
                  cache[hash] = target;
              }
          }

          File 2 of 6: 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 3 of 6: Vat
          // hevm: flattened sources of /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/vat.sol
          pragma solidity =0.5.12;
          
          ////// /nix/store/8xb41r4qd0cjb63wcrxf1qmfg88p0961-dss-6fd7de0/src/vat.sol
          /// vat.sol -- Dai CDP database
          
          // Copyright (C) 2018 Rain <[email protected]>
          //
          // This program is free software: you can redistribute it and/or modify
          // it under the terms of the GNU Affero General Public License as published by
          // the Free Software Foundation, either version 3 of the License, or
          // (at your option) any later version.
          //
          // This program is distributed in the hope that it will be useful,
          // but WITHOUT ANY WARRANTY; without even the implied warranty of
          // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
          // GNU Affero General Public License for more details.
          //
          // You should have received a copy of the GNU Affero General Public License
          // along with this program.  If not, see <https://www.gnu.org/licenses/>.
          
          /* pragma solidity 0.5.12; */
          
          contract Vat {
              // --- Auth ---
              mapping (address => uint) public wards;
              function rely(address usr) external note auth { require(live == 1, "Vat/not-live"); wards[usr] = 1; }
              function deny(address usr) external note auth { require(live == 1, "Vat/not-live"); wards[usr] = 0; }
              modifier auth {
                  require(wards[msg.sender] == 1, "Vat/not-authorized");
                  _;
              }
          
              mapping(address => mapping (address => uint)) public can;
              function hope(address usr) external note { can[msg.sender][usr] = 1; }
              function nope(address usr) external note { can[msg.sender][usr] = 0; }
              function wish(address bit, address usr) internal view returns (bool) {
                  return either(bit == usr, can[bit][usr] == 1);
              }
          
              // --- Data ---
              struct Ilk {
                  uint256 Art;   // Total Normalised Debt     [wad]
                  uint256 rate;  // Accumulated Rates         [ray]
                  uint256 spot;  // Price with Safety Margin  [ray]
                  uint256 line;  // Debt Ceiling              [rad]
                  uint256 dust;  // Urn Debt Floor            [rad]
              }
              struct Urn {
                  uint256 ink;   // Locked Collateral  [wad]
                  uint256 art;   // Normalised Debt    [wad]
              }
          
              mapping (bytes32 => Ilk)                       public ilks;
              mapping (bytes32 => mapping (address => Urn )) public urns;
              mapping (bytes32 => mapping (address => uint)) public gem;  // [wad]
              mapping (address => uint256)                   public dai;  // [rad]
              mapping (address => uint256)                   public sin;  // [rad]
          
              uint256 public debt;  // Total Dai Issued    [rad]
              uint256 public vice;  // Total Unbacked Dai  [rad]
              uint256 public Line;  // Total Debt Ceiling  [rad]
              uint256 public live;  // Access Flag
          
              // --- Logs ---
              event LogNote(
                  bytes4   indexed  sig,
                  bytes32  indexed  arg1,
                  bytes32  indexed  arg2,
                  bytes32  indexed  arg3,
                  bytes             data
              ) anonymous;
          
              modifier note {
                  _;
                  assembly {
                      // log an 'anonymous' event with a constant 6 words of calldata
                      // and four indexed topics: the selector and the first three args
                      let mark := msize                         // end of memory ensures zero
                      mstore(0x40, add(mark, 288))              // update free memory pointer
                      mstore(mark, 0x20)                        // bytes type data offset
                      mstore(add(mark, 0x20), 224)              // bytes size (padded)
                      calldatacopy(add(mark, 0x40), 0, 224)     // bytes payload
                      log4(mark, 288,                           // calldata
                           shl(224, shr(224, calldataload(0))), // msg.sig
                           calldataload(4),                     // arg1
                           calldataload(36),                    // arg2
                           calldataload(68)                     // arg3
                          )
                  }
              }
          
              // --- Init ---
              constructor() public {
                  wards[msg.sender] = 1;
                  live = 1;
              }
          
              // --- Math ---
              function add(uint x, int y) internal pure returns (uint z) {
                  z = x + uint(y);
                  require(y >= 0 || z <= x);
                  require(y <= 0 || z >= x);
              }
              function sub(uint x, int y) internal pure returns (uint z) {
                  z = x - uint(y);
                  require(y <= 0 || z <= x);
                  require(y >= 0 || z >= x);
              }
              function mul(uint x, int y) internal pure returns (int z) {
                  z = int(x) * y;
                  require(int(x) >= 0);
                  require(y == 0 || z / y == int(x));
              }
              function add(uint x, uint y) internal pure returns (uint z) {
                  require((z = x + y) >= x);
              }
              function sub(uint x, uint y) internal pure returns (uint z) {
                  require((z = x - y) <= x);
              }
              function mul(uint x, uint y) internal pure returns (uint z) {
                  require(y == 0 || (z = x * y) / y == x);
              }
          
              // --- Administration ---
              function init(bytes32 ilk) external note auth {
                  require(ilks[ilk].rate == 0, "Vat/ilk-already-init");
                  ilks[ilk].rate = 10 ** 27;
              }
              function file(bytes32 what, uint data) external note auth {
                  require(live == 1, "Vat/not-live");
                  if (what == "Line") Line = data;
                  else revert("Vat/file-unrecognized-param");
              }
              function file(bytes32 ilk, bytes32 what, uint data) external note auth {
                  require(live == 1, "Vat/not-live");
                  if (what == "spot") ilks[ilk].spot = data;
                  else if (what == "line") ilks[ilk].line = data;
                  else if (what == "dust") ilks[ilk].dust = data;
                  else revert("Vat/file-unrecognized-param");
              }
              function cage() external note auth {
                  live = 0;
              }
          
              // --- Fungibility ---
              function slip(bytes32 ilk, address usr, int256 wad) external note auth {
                  gem[ilk][usr] = add(gem[ilk][usr], wad);
              }
              function flux(bytes32 ilk, address src, address dst, uint256 wad) external note {
                  require(wish(src, msg.sender), "Vat/not-allowed");
                  gem[ilk][src] = sub(gem[ilk][src], wad);
                  gem[ilk][dst] = add(gem[ilk][dst], wad);
              }
              function move(address src, address dst, uint256 rad) external note {
                  require(wish(src, msg.sender), "Vat/not-allowed");
                  dai[src] = sub(dai[src], rad);
                  dai[dst] = add(dai[dst], rad);
              }
          
              function either(bool x, bool y) internal pure returns (bool z) {
                  assembly{ z := or(x, y)}
              }
              function both(bool x, bool y) internal pure returns (bool z) {
                  assembly{ z := and(x, y)}
              }
          
              // --- CDP Manipulation ---
              function frob(bytes32 i, address u, address v, address w, int dink, int dart) external note {
                  // system is live
                  require(live == 1, "Vat/not-live");
          
                  Urn memory urn = urns[i][u];
                  Ilk memory ilk = ilks[i];
                  // ilk has been initialised
                  require(ilk.rate != 0, "Vat/ilk-not-init");
          
                  urn.ink = add(urn.ink, dink);
                  urn.art = add(urn.art, dart);
                  ilk.Art = add(ilk.Art, dart);
          
                  int dtab = mul(ilk.rate, dart);
                  uint tab = mul(ilk.rate, urn.art);
                  debt     = add(debt, dtab);
          
                  // either debt has decreased, or debt ceilings are not exceeded
                  require(either(dart <= 0, both(mul(ilk.Art, ilk.rate) <= ilk.line, debt <= Line)), "Vat/ceiling-exceeded");
                  // urn is either less risky than before, or it is safe
                  require(either(both(dart <= 0, dink >= 0), tab <= mul(urn.ink, ilk.spot)), "Vat/not-safe");
          
                  // urn is either more safe, or the owner consents
                  require(either(both(dart <= 0, dink >= 0), wish(u, msg.sender)), "Vat/not-allowed-u");
                  // collateral src consents
                  require(either(dink <= 0, wish(v, msg.sender)), "Vat/not-allowed-v");
                  // debt dst consents
                  require(either(dart >= 0, wish(w, msg.sender)), "Vat/not-allowed-w");
          
                  // urn has no debt, or a non-dusty amount
                  require(either(urn.art == 0, tab >= ilk.dust), "Vat/dust");
          
                  gem[i][v] = sub(gem[i][v], dink);
                  dai[w]    = add(dai[w],    dtab);
          
                  urns[i][u] = urn;
                  ilks[i]    = ilk;
              }
              // --- CDP Fungibility ---
              function fork(bytes32 ilk, address src, address dst, int dink, int dart) external note {
                  Urn storage u = urns[ilk][src];
                  Urn storage v = urns[ilk][dst];
                  Ilk storage i = ilks[ilk];
          
                  u.ink = sub(u.ink, dink);
                  u.art = sub(u.art, dart);
                  v.ink = add(v.ink, dink);
                  v.art = add(v.art, dart);
          
                  uint utab = mul(u.art, i.rate);
                  uint vtab = mul(v.art, i.rate);
          
                  // both sides consent
                  require(both(wish(src, msg.sender), wish(dst, msg.sender)), "Vat/not-allowed");
          
                  // both sides safe
                  require(utab <= mul(u.ink, i.spot), "Vat/not-safe-src");
                  require(vtab <= mul(v.ink, i.spot), "Vat/not-safe-dst");
          
                  // both sides non-dusty
                  require(either(utab >= i.dust, u.art == 0), "Vat/dust-src");
                  require(either(vtab >= i.dust, v.art == 0), "Vat/dust-dst");
              }
              // --- CDP Confiscation ---
              function grab(bytes32 i, address u, address v, address w, int dink, int dart) external note auth {
                  Urn storage urn = urns[i][u];
                  Ilk storage ilk = ilks[i];
          
                  urn.ink = add(urn.ink, dink);
                  urn.art = add(urn.art, dart);
                  ilk.Art = add(ilk.Art, dart);
          
                  int dtab = mul(ilk.rate, dart);
          
                  gem[i][v] = sub(gem[i][v], dink);
                  sin[w]    = sub(sin[w],    dtab);
                  vice      = sub(vice,      dtab);
              }
          
              // --- Settlement ---
              function heal(uint rad) external note {
                  address u = msg.sender;
                  sin[u] = sub(sin[u], rad);
                  dai[u] = sub(dai[u], rad);
                  vice   = sub(vice,   rad);
                  debt   = sub(debt,   rad);
              }
              function suck(address u, address v, uint rad) external note auth {
                  sin[u] = add(sin[u], rad);
                  dai[v] = add(dai[v], rad);
                  vice   = add(vice,   rad);
                  debt   = add(debt,   rad);
              }
          
              // --- Rates ---
              function fold(bytes32 i, address u, int rate) external note auth {
                  require(live == 1, "Vat/not-live");
                  Ilk storage ilk = ilks[i];
                  ilk.rate = add(ilk.rate, rate);
                  int rad  = mul(ilk.Art, rate);
                  dai[u]   = add(dai[u], rad);
                  debt     = add(debt,   rad);
              }
          }

          File 4 of 6: 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 5 of 6: DssCdpManager
          // hevm: flattened sources of /nix/store/jyvwn5yyqxwkfxc45k04h2dk209dn6sh-dss-cdp-manager-8976239/src/DssCdpManager.sol
          pragma solidity =0.5.12;
          
          ////// /nix/store/4vip6nyqfd0yhs15md21rzxsk5jgx6sv-dss/dapp/dss/src/lib.sol
          // This program is free software: you can redistribute it and/or modify
          // it under the terms of the GNU General Public License as published by
          // the Free Software Foundation, either version 3 of the License, or
          // (at your option) any later version.
          
          // This program is distributed in the hope that it will be useful,
          // but WITHOUT ANY WARRANTY; without even the implied warranty of
          // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
          // GNU General Public License for more details.
          
          // You should have received a copy of the GNU General Public License
          // along with this program.  If not, see <http://www.gnu.org/licenses/>.
          
          /* pragma solidity 0.5.12; */
          
          contract LibNote {
              event LogNote(
                  bytes4   indexed  sig,
                  address  indexed  usr,
                  bytes32  indexed  arg1,
                  bytes32  indexed  arg2,
                  bytes             data
              ) anonymous;
          
              modifier note {
                  _;
                  assembly {
                      // log an 'anonymous' event with a constant 6 words of calldata
                      // and four indexed topics: selector, caller, arg1 and arg2
                      let mark := msize                         // end of memory ensures zero
                      mstore(0x40, add(mark, 288))              // update free memory pointer
                      mstore(mark, 0x20)                        // bytes type data offset
                      mstore(add(mark, 0x20), 224)              // bytes size (padded)
                      calldatacopy(add(mark, 0x40), 0, 224)     // bytes payload
                      log4(mark, 288,                           // calldata
                           shl(224, shr(224, calldataload(0))), // msg.sig
                           caller,                              // msg.sender
                           calldataload(4),                     // arg1
                           calldataload(36)                     // arg2
                          )
                  }
              }
          }
          
          ////// /nix/store/jyvwn5yyqxwkfxc45k04h2dk209dn6sh-dss-cdp-manager-8976239/src/DssCdpManager.sol
          /* pragma solidity 0.5.12; */
          
          /* import { LibNote } from "dss/lib.sol"; */
          
          contract VatLike {
              function urns(bytes32, address) public view returns (uint, uint);
              function hope(address) public;
              function flux(bytes32, address, address, uint) public;
              function move(address, address, uint) public;
              function frob(bytes32, address, address, address, int, int) public;
              function fork(bytes32, address, address, int, int) public;
          }
          
          contract UrnHandler {
              constructor(address vat) public {
                  VatLike(vat).hope(msg.sender);
              }
          }
          
          contract DssCdpManager is LibNote {
              address                   public vat;
              uint                      public cdpi;      // Auto incremental
              mapping (uint => address) public urns;      // CDPId => UrnHandler
              mapping (uint => List)    public list;      // CDPId => Prev & Next CDPIds (double linked list)
              mapping (uint => address) public owns;      // CDPId => Owner
              mapping (uint => bytes32) public ilks;      // CDPId => Ilk
          
              mapping (address => uint) public first;     // Owner => First CDPId
              mapping (address => uint) public last;      // Owner => Last CDPId
              mapping (address => uint) public count;     // Owner => Amount of CDPs
          
              mapping (
                  address => mapping (
                      uint => mapping (
                          address => uint
                      )
                  )
              ) public cdpCan;                            // Owner => CDPId => Allowed Addr => True/False
          
              mapping (
                  address => mapping (
                      address => uint
                  )
              ) public urnCan;                            // Urn => Allowed Addr => True/False
          
              struct List {
                  uint prev;
                  uint next;
              }
          
              event NewCdp(address indexed usr, address indexed own, uint indexed cdp);
          
              modifier cdpAllowed(
                  uint cdp
              ) {
                  require(msg.sender == owns[cdp] || cdpCan[owns[cdp]][cdp][msg.sender] == 1, "cdp-not-allowed");
                  _;
              }
          
              modifier urnAllowed(
                  address urn
              ) {
                  require(msg.sender == urn || urnCan[urn][msg.sender] == 1, "urn-not-allowed");
                  _;
              }
          
              constructor(address vat_) public {
                  vat = vat_;
              }
          
              function add(uint x, uint y) internal pure returns (uint z) {
                  require((z = x + y) >= x);
              }
          
              function sub(uint x, uint y) internal pure returns (uint z) {
                  require((z = x - y) <= x);
              }
          
              function toInt(uint x) internal pure returns (int y) {
                  y = int(x);
                  require(y >= 0);
              }
          
              // Allow/disallow a usr address to manage the cdp.
              function cdpAllow(
                  uint cdp,
                  address usr,
                  uint ok
              ) public cdpAllowed(cdp) {
                  cdpCan[owns[cdp]][cdp][usr] = ok;
              }
          
              // Allow/disallow a usr address to quit to the the sender urn.
              function urnAllow(
                  address usr,
                  uint ok
              ) public {
                  urnCan[msg.sender][usr] = ok;
              }
          
              // Open a new cdp for a given usr address.
              function open(
                  bytes32 ilk,
                  address usr
              ) public note returns (uint) {
                  require(usr != address(0), "usr-address-0");
          
                  cdpi = add(cdpi, 1);
                  urns[cdpi] = address(new UrnHandler(vat));
                  owns[cdpi] = usr;
                  ilks[cdpi] = ilk;
          
                  // Add new CDP to double linked list and pointers
                  if (first[usr] == 0) {
                      first[usr] = cdpi;
                  }
                  if (last[usr] != 0) {
                      list[cdpi].prev = last[usr];
                      list[last[usr]].next = cdpi;
                  }
                  last[usr] = cdpi;
                  count[usr] = add(count[usr], 1);
          
                  emit NewCdp(msg.sender, usr, cdpi);
                  return cdpi;
              }
          
              // Give the cdp ownership to a dst address.
              function give(
                  uint cdp,
                  address dst
              ) public note cdpAllowed(cdp) {
                  require(dst != address(0), "dst-address-0");
                  require(dst != owns[cdp], "dst-already-owner");
          
                  // Remove transferred CDP from double linked list of origin user and pointers
                  if (list[cdp].prev != 0) {
                      list[list[cdp].prev].next = list[cdp].next;         // Set the next pointer of the prev cdp (if exists) to the next of the transferred one
                  }
                  if (list[cdp].next != 0) {                              // If wasn't the last one
                      list[list[cdp].next].prev = list[cdp].prev;         // Set the prev pointer of the next cdp to the prev of the transferred one
                  } else {                                                // If was the last one
                      last[owns[cdp]] = list[cdp].prev;                   // Update last pointer of the owner
                  }
                  if (first[owns[cdp]] == cdp) {                          // If was the first one
                      first[owns[cdp]] = list[cdp].next;                  // Update first pointer of the owner
                  }
                  count[owns[cdp]] = sub(count[owns[cdp]], 1);
          
                  // Transfer ownership
                  owns[cdp] = dst;
          
                  // Add transferred CDP to double linked list of destiny user and pointers
                  list[cdp].prev = last[dst];
                  list[cdp].next = 0;
                  if (last[dst] != 0) {
                      list[last[dst]].next = cdp;
                  }
                  if (first[dst] == 0) {
                      first[dst] = cdp;
                  }
                  last[dst] = cdp;
                  count[dst] = add(count[dst], 1);
              }
          
              // Frob the cdp keeping the generated DAI or collateral freed in the cdp urn address.
              function frob(
                  uint cdp,
                  int dink,
                  int dart
              ) public note cdpAllowed(cdp) {
                  address urn = urns[cdp];
                  VatLike(vat).frob(
                      ilks[cdp],
                      urn,
                      urn,
                      urn,
                      dink,
                      dart
                  );
              }
          
              // Transfer wad amount of cdp collateral from the cdp address to a dst address.
              function flux(
                  uint cdp,
                  address dst,
                  uint wad
              ) public note cdpAllowed(cdp) {
                  VatLike(vat).flux(ilks[cdp], urns[cdp], dst, wad);
              }
          
              // Transfer wad amount of any type of collateral (ilk) from the cdp address to a dst address.
              // This function has the purpose to take away collateral from the system that doesn't correspond to the cdp but was sent there wrongly.
              function flux(
                  bytes32 ilk,
                  uint cdp,
                  address dst,
                  uint wad
              ) public note cdpAllowed(cdp) {
                  VatLike(vat).flux(ilk, urns[cdp], dst, wad);
              }
          
              // Transfer wad amount of DAI from the cdp address to a dst address.
              function move(
                  uint cdp,
                  address dst,
                  uint rad
              ) public note cdpAllowed(cdp) {
                  VatLike(vat).move(urns[cdp], dst, rad);
              }
          
              // Quit the system, migrating the cdp (ink, art) to a different dst urn
              function quit(
                  uint cdp,
                  address dst
              ) public note cdpAllowed(cdp) urnAllowed(dst) {
                  (uint ink, uint art) = VatLike(vat).urns(ilks[cdp], urns[cdp]);
                  VatLike(vat).fork(
                      ilks[cdp],
                      urns[cdp],
                      dst,
                      toInt(ink),
                      toInt(art)
                  );
              }
          
              // Import a position from src urn to the urn owned by cdp
              function enter(
                  address src,
                  uint cdp
              ) public note urnAllowed(src) cdpAllowed(cdp) {
                  (uint ink, uint art) = VatLike(vat).urns(ilks[cdp], src);
                  VatLike(vat).fork(
                      ilks[cdp],
                      src,
                      urns[cdp],
                      toInt(ink),
                      toInt(art)
                  );
              }
          
              // Move a position from cdpSrc urn to the cdpDst urn
              function shift(
                  uint cdpSrc,
                  uint cdpDst
              ) public note cdpAllowed(cdpSrc) cdpAllowed(cdpDst) {
                  require(ilks[cdpSrc] == ilks[cdpDst], "non-matching-cdps");
                  (uint ink, uint art) = VatLike(vat).urns(ilks[cdpSrc], urns[cdpSrc]);
                  VatLike(vat).fork(
                      ilks[cdpSrc],
                      urns[cdpSrc],
                      urns[cdpDst],
                      toInt(ink),
                      toInt(art)
                  );
              }
          }

          File 6 of 6: SaverProxyActions
          pragma solidity ^0.5.0;
          
          contract GemLike {
              function approve(address, uint) public;
              function transfer(address, uint) public;
              function transferFrom(address, address, uint) public;
              function deposit() public payable;
              function withdraw(uint) public;
          }
          
          contract ManagerLike {
              function cdpCan(address, uint, address) public view returns (uint);
              function ilks(uint) public view returns (bytes32);
              function owns(uint) public view returns (address);
              function urns(uint) public view returns (address);
              function vat() public view returns (address);
              function open(bytes32, address) public returns (uint);
              function give(uint, address) public;
              function cdpAllow(uint, address, uint) public;
              function urnAllow(address, uint) public;
              function frob(uint, int, int) public;
              function flux(uint, address, uint) public;
              function move(uint, address, uint) public;
              function exit(address, uint, address, uint) public;
              function quit(uint, address) public;
              function enter(address, uint) public;
              function shift(uint, uint) public;
          }
          
          contract VatLike {
              function can(address, address) public view returns (uint);
              function ilks(bytes32) public view returns (uint, uint, uint, uint, uint);
              function dai(address) public view returns (uint);
              function urns(bytes32, address) public view returns (uint, uint);
              function frob(bytes32, address, address, address, int, int) public;
              function hope(address) public;
              function move(address, address, uint) public;
          }
          
          contract GemJoinLike {
              function dec() public returns (uint);
              function gem() public returns (GemLike);
              function join(address, uint) public payable;
              function exit(address, uint) public;
          }
          
          contract GNTJoinLike {
              function bags(address) public view returns (address);
              function make(address) public returns (address);
          }
          
          contract DaiJoinLike {
              function vat() public returns (VatLike);
              function dai() public returns (GemLike);
              function join(address, uint) public payable;
              function exit(address, uint) public;
          }
          
          contract HopeLike {
              function hope(address) public;
              function nope(address) public;
          }
          
          contract ProxyRegistryInterface {
              function build(address) public returns (address);
          }
          
          contract EndLike {
              function fix(bytes32) public view returns (uint);
              function cash(bytes32, uint) public;
              function free(bytes32) public;
              function pack(uint) public;
              function skim(bytes32, address) public;
          }
          
          contract JugLike {
              function drip(bytes32) public returns (uint);
          }
          
          contract PotLike {
              function pie(address) public view returns (uint);
              function drip() public returns (uint);
              function join(uint) public;
              function exit(uint) public;
          }
          
          contract ProxyRegistryLike {
              function proxies(address) public view returns (address);
              function build(address) public returns (address);
          }
          
          contract ProxyLike {
              function owner() public view returns (address);
          }
          
          contract DSProxy {
              function execute(address _target, bytes memory _data) public payable returns (bytes32);
              function setOwner(address owner_) public;
          }
          
          // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
          // WARNING: These functions meant to be used as a a library for a DSProxy. Some are unsafe if you call them directly.
          // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
          
          contract Common {
              uint256 constant RAY = 10 ** 27;
          
              // Internal functions
          
              function mul(uint x, uint y) internal pure returns (uint z) {
                  require(y == 0 || (z = x * y) / y == x, "mul-overflow");
              }
          
              // Public functions
          
              function daiJoin_join(address apt, address urn, uint wad) public {
                  // Gets DAI from the user's wallet
                  DaiJoinLike(apt).dai().transferFrom(msg.sender, address(this), wad);
                  // Approves adapter to take the DAI amount
                  DaiJoinLike(apt).dai().approve(apt, wad);
                  // Joins DAI into the vat
                  DaiJoinLike(apt).join(urn, wad);
              }
          }
          
          contract SaverProxyActions is Common {
          
          
              event CDPAction(string indexed, uint indexed, uint, uint);
          
              // Internal functions
          
              function sub(uint x, uint y) internal pure returns (uint z) {
                  require((z = x - y) <= x, "sub-overflow");
              }
          
              function toInt(uint x) internal pure returns (int y) {
                  y = int(x);
                  require(y >= 0, "int-overflow");
              }
          
              function toRad(uint wad) internal pure returns (uint rad) {
                  rad = mul(wad, 10 ** 27);
              }
          
              function convertTo18(address gemJoin, uint256 amt) internal returns (uint256 wad) {
                  // For those collaterals that have less than 18 decimals precision we need to do the conversion before passing to frob function
                  // Adapters will automatically handle the difference of precision
                  wad = mul(
                      amt,
                      10 ** (18 - GemJoinLike(gemJoin).dec())
                  );
              }
          
              function _getDrawDart(
                  address vat,
                  address jug,
                  address urn,
                  bytes32 ilk,
                  uint wad
              ) internal returns (int dart) {
                  // Updates stability fee rate
                  uint rate = JugLike(jug).drip(ilk);
          
                  // Gets DAI balance of the urn in the vat
                  uint dai = VatLike(vat).dai(urn);
          
                  // If there was already enough DAI in the vat balance, just exits it without adding more debt
                  if (dai < mul(wad, RAY)) {
                      // Calculates the needed dart so together with the existing dai in the vat is enough to exit wad amount of DAI tokens
                      dart = toInt(sub(mul(wad, RAY), dai) / rate);
                      // This is neeeded due lack of precision. It might need to sum an extra dart wei (for the given DAI wad amount)
                      dart = mul(uint(dart), rate) < mul(wad, RAY) ? dart + 1 : dart;
                  }
              }
          
              function _getWipeDart(
                  address vat,
                  uint dai,
                  address urn,
                  bytes32 ilk
              ) internal view returns (int dart) {
                  // Gets actual rate from the vat
                  (, uint rate,,,) = VatLike(vat).ilks(ilk);
                  // Gets actual art value of the urn
                  (, uint art) = VatLike(vat).urns(ilk, urn);
          
                  // Uses the whole dai balance in the vat to reduce the debt
                  dart = toInt(dai / rate);
                  // Checks the calculated dart is not higher than urn.art (total debt), otherwise uses its value
                  dart = uint(dart) <= art ? - dart : - toInt(art);
              }
          
              function _getWipeAllWad(
                  address vat,
                  address usr,
                  address urn,
                  bytes32 ilk
              ) internal view returns (uint wad) {
                  // Gets actual rate from the vat
                  (, uint rate,,,) = VatLike(vat).ilks(ilk);
                  // Gets actual art value of the urn
                  (, uint art) = VatLike(vat).urns(ilk, urn);
                  // Gets actual dai amount in the urn
                  uint dai = VatLike(vat).dai(usr);
          
                  uint rad = sub(mul(art, rate), dai);
                  wad = rad / RAY;
          
                  // If the rad precision has some dust, it will need to request for 1 extra wad wei
                  wad = mul(wad, RAY) < rad ? wad + 1 : wad;
              }
          
              // Public functions
          
              function transfer(address gem, address dst, uint wad) public {
                  GemLike(gem).transfer(dst, wad);
              }
          
              function ethJoin_join(address apt, address urn) public payable {
                  // Wraps ETH in WETH
                  GemJoinLike(apt).gem().deposit.value(msg.value)();
                  // Approves adapter to take the WETH amount
                  GemJoinLike(apt).gem().approve(address(apt), msg.value);
                  // Joins WETH collateral into the vat
                  GemJoinLike(apt).join(urn, msg.value);
              }
          
              function gemJoin_join(address apt, address urn, uint wad, bool transferFrom) public {
                  // Only executes for tokens that have approval/transferFrom implementation
                  if (transferFrom) {
                      // Gets token from the user's wallet
                      GemJoinLike(apt).gem().transferFrom(msg.sender, address(this), wad);
                      // Approves adapter to take the token amount
                      GemJoinLike(apt).gem().approve(apt, wad);
                  }
                  // Joins token collateral into the vat
                  GemJoinLike(apt).join(urn, wad);
              }
          
              function hope(
                  address obj,
                  address usr
              ) public {
                  HopeLike(obj).hope(usr);
              }
          
              function nope(
                  address obj,
                  address usr
              ) public {
                  HopeLike(obj).nope(usr);
              }
          
              function open(
                  address manager,
                  bytes32 ilk,
                  address usr
              ) public returns (uint cdp) {
                  cdp = ManagerLike(manager).open(ilk, usr);
              }
          
              function give(
                  address manager,
                  uint cdp,
                  address usr
              ) public {
                  ManagerLike(manager).give(cdp, usr);
          
                  emit CDPAction('give', cdp, 0, 0);
              }
          
              function giveToProxy(
                  address proxyRegistry,
                  address manager,
                  uint cdp,
                  address dst
              ) public {
                  // Gets actual proxy address
                  address proxy = ProxyRegistryLike(proxyRegistry).proxies(dst);
                  // Checks if the proxy address already existed and dst address is still the owner
                  if (proxy == address(0) || ProxyLike(proxy).owner() != dst) {
                      uint csize;
                      assembly {
                          csize := extcodesize(dst)
                      }
                      // We want to avoid creating a proxy for a contract address that might not be able to handle proxies, then losing the CDP
                      require(csize == 0, "Dst-is-a-contract");
                      // Creates the proxy for the dst address
                      proxy = ProxyRegistryLike(proxyRegistry).build(dst);
                  }
                  // Transfers CDP to the dst proxy
                  give(manager, cdp, proxy);
              }
          
              function cdpAllow(
                  address manager,
                  uint cdp,
                  address usr,
                  uint ok
              ) public {
                  ManagerLike(manager).cdpAllow(cdp, usr, ok);
              }
          
              function urnAllow(
                  address manager,
                  address usr,
                  uint ok
              ) public {
                  ManagerLike(manager).urnAllow(usr, ok);
              }
          
              function flux(
                  address manager,
                  uint cdp,
                  address dst,
                  uint wad
              ) public {
                  ManagerLike(manager).flux(cdp, dst, wad);
              }
          
              function move(
                  address manager,
                  uint cdp,
                  address dst,
                  uint rad
              ) public {
                  ManagerLike(manager).move(cdp, dst, rad);
              }
          
              function frob(
                  address manager,
                  uint cdp,
                  int dink,
                  int dart
              ) public {
                  ManagerLike(manager).frob(cdp, dink, dart);
              }
          
              function quit(
                  address manager,
                  uint cdp,
                  address dst
              ) public {
                  ManagerLike(manager).quit(cdp, dst);
              }
          
              function enter(
                  address manager,
                  address src,
                  uint cdp
              ) public {
                  ManagerLike(manager).enter(src, cdp);
              }
          
              function shift(
                  address manager,
                  uint cdpSrc,
                  uint cdpOrg
              ) public {
                  ManagerLike(manager).shift(cdpSrc, cdpOrg);
              }
          
              function makeGemBag(
                  address gemJoin
              ) public returns (address bag) {
                  bag = GNTJoinLike(gemJoin).make(address(this));
              }
          
              function lockETH(
                  address manager,
                  address ethJoin,
                  uint cdp
              ) public payable {
                  // Receives ETH amount, converts it to WETH and joins it into the vat
                  ethJoin_join(ethJoin, address(this));
                  // Locks WETH amount into the CDP
                  VatLike(ManagerLike(manager).vat()).frob(
                      ManagerLike(manager).ilks(cdp),
                      ManagerLike(manager).urns(cdp),
                      address(this),
                      address(this),
                      toInt(msg.value),
                      0
                  );
          
                  emit CDPAction('lockETH', cdp, msg.value, 0);
              }
          
              function lockGem(
                  address manager,
                  address gemJoin,
                  uint cdp,
                  uint wad,
                  bool transferFrom
              ) public {
                  // Takes token amount from user's wallet and joins into the vat
                  gemJoin_join(gemJoin, address(this), wad, transferFrom);
                  // Locks token amount into the CDP
                  VatLike(ManagerLike(manager).vat()).frob(
                      ManagerLike(manager).ilks(cdp),
                      ManagerLike(manager).urns(cdp),
                      address(this),
                      address(this),
                      toInt(convertTo18(gemJoin, wad)),
                      0
                  );
          
                  emit CDPAction('lockGem', cdp, wad, 0);
              }
          
              function freeETH(
                  address manager,
                  address ethJoin,
                  uint cdp,
                  uint wad
              ) public {
                  // Unlocks WETH amount from the CDP
                  frob(manager, cdp, -toInt(wad), 0);
                  // Moves the amount from the CDP urn to proxy's address
                  flux(manager, cdp, address(this), wad);
                  // Exits WETH amount to proxy address as a token
                  GemJoinLike(ethJoin).exit(address(this), wad);
                  // Converts WETH to ETH
                  GemJoinLike(ethJoin).gem().withdraw(wad);
                  // Sends ETH back to the user's wallet
                  msg.sender.transfer(wad);
          
                  emit CDPAction('freeETH', cdp, wad, 0);
              }
          
              function freeGem(
                  address manager,
                  address gemJoin,
                  uint cdp,
                  uint wad
              ) public {
                  uint wad18 = convertTo18(gemJoin, wad);
                  // Unlocks token amount from the CDP
                  frob(manager, cdp, -toInt(wad18), 0);
                  // Moves the amount from the CDP urn to proxy's address
                  flux(manager, cdp, address(this), wad18);
                  // Exits token amount to the user's wallet as a token
                  GemJoinLike(gemJoin).exit(msg.sender, wad);
          
                  emit CDPAction('freeGem', cdp, wad, 0);
              }
          
              function exitETH(
                  address manager,
                  address ethJoin,
                  uint cdp,
                  uint wad
              ) public {
                  // Moves the amount from the CDP urn to proxy's address
                  flux(manager, cdp, address(this), wad);
          
                  // Exits WETH amount to proxy address as a token
                  GemJoinLike(ethJoin).exit(address(this), wad);
                  // Converts WETH to ETH
                  GemJoinLike(ethJoin).gem().withdraw(wad);
                  // Sends ETH back to the user's wallet
                  msg.sender.transfer(wad);
              }
          
              function exitGem(
                  address manager,
                  address gemJoin,
                  uint cdp,
                  uint wad
              ) public {
                  // Moves the amount from the CDP urn to proxy's address
                  flux(manager, cdp, address(this), convertTo18(gemJoin, wad));
          
                  // Exits token amount to the user's wallet as a token
                  GemJoinLike(gemJoin).exit(msg.sender, wad);
              }
          
              function draw(
                  address manager,
                  address jug,
                  address daiJoin,
                  uint cdp,
                  uint wad
              ) public {
                  address urn = ManagerLike(manager).urns(cdp);
                  address vat = ManagerLike(manager).vat();
                  bytes32 ilk = ManagerLike(manager).ilks(cdp);
                  // Generates debt in the CDP
                  frob(manager, cdp, 0, _getDrawDart(vat, jug, urn, ilk, wad));
                  // Moves the DAI amount (balance in the vat in rad) to proxy's address
                  move(manager, cdp, address(this), toRad(wad));
                  // Allows adapter to access to proxy's DAI balance in the vat
                  if (VatLike(vat).can(address(this), address(daiJoin)) == 0) {
                      VatLike(vat).hope(daiJoin);
                  }
                  // Exits DAI to the user's wallet as a token
                  DaiJoinLike(daiJoin).exit(msg.sender, wad);
          
                  emit CDPAction('draw', cdp, 0, wad);
              }
          
              function wipe(
                  address manager,
                  address daiJoin,
                  uint cdp,
                  uint wad
              ) public {
                  address vat = ManagerLike(manager).vat();
                  address urn = ManagerLike(manager).urns(cdp);
                  bytes32 ilk = ManagerLike(manager).ilks(cdp);
          
                  address own = ManagerLike(manager).owns(cdp);
                  if (own == address(this) || ManagerLike(manager).cdpCan(own, cdp, address(this)) == 1) {
                      // Joins DAI amount into the vat
                      daiJoin_join(daiJoin, urn, wad);
                      // Paybacks debt to the CDP
                      frob(manager, cdp, 0, _getWipeDart(vat, VatLike(vat).dai(urn), urn, ilk));
                  } else {
                       // Joins DAI amount into the vat
                      daiJoin_join(daiJoin, address(this), wad);
                      // Paybacks debt to the CDP
                      VatLike(vat).frob(
                          ilk,
                          urn,
                          address(this),
                          address(this),
                          0,
                          _getWipeDart(vat, wad * RAY, urn, ilk)
                      );
                  }
          
                  emit CDPAction('wipe', cdp, 0, wad);
              }
          
              function wipeAll(
                  address manager,
                  address daiJoin,
                  uint cdp
              ) public {
                  address vat = ManagerLike(manager).vat();
                  address urn = ManagerLike(manager).urns(cdp);
                  bytes32 ilk = ManagerLike(manager).ilks(cdp);
                  (, uint art) = VatLike(vat).urns(ilk, urn);
          
                  address own = ManagerLike(manager).owns(cdp);
                  if (own == address(this) || ManagerLike(manager).cdpCan(own, cdp, address(this)) == 1) {
                      // Joins DAI amount into the vat
                      daiJoin_join(daiJoin, urn, _getWipeAllWad(vat, urn, urn, ilk));
                      // Paybacks debt to the CDP
                      frob(manager, cdp, 0, -int(art));
                  } else {
                      // Joins DAI amount into the vat
                      daiJoin_join(daiJoin, address(this), _getWipeAllWad(vat, address(this), urn, ilk));
                      // Paybacks debt to the CDP
                      VatLike(vat).frob(
                          ilk,
                          urn,
                          address(this),
                          address(this),
                          0,
                          -int(art)
                      );
                  }
          
                  emit CDPAction('wipeAll', cdp, 0, art);
              }
          
              function lockETHAndDraw(
                  address manager,
                  address jug,
                  address ethJoin,
                  address daiJoin,
                  uint cdp,
                  uint wadD
              ) public payable {
                  address urn = ManagerLike(manager).urns(cdp);
                  address vat = ManagerLike(manager).vat();
                  bytes32 ilk = ManagerLike(manager).ilks(cdp);
                  // Receives ETH amount, converts it to WETH and joins it into the vat
                  ethJoin_join(ethJoin, urn);
                  // Locks WETH amount into the CDP and generates debt
                  frob(manager, cdp, toInt(msg.value), _getDrawDart(vat, jug, urn, ilk, wadD));
                  // Moves the DAI amount (balance in the vat in rad) to proxy's address
                  move(manager, cdp, address(this), toRad(wadD));
                  // Allows adapter to access to proxy's DAI balance in the vat
                  if (VatLike(vat).can(address(this), address(daiJoin)) == 0) {
                      VatLike(vat).hope(daiJoin);
                  }
                  // Exits DAI to the user's wallet as a token
                  DaiJoinLike(daiJoin).exit(msg.sender, wadD);
              }
          
              function openLockETHAndDraw(
                  address manager,
                  address jug,
                  address ethJoin,
                  address daiJoin,
                  bytes32 ilk,
                  uint wadD
              ) public payable returns (uint cdp) {
                  cdp = open(manager, ilk, address(this));
                  lockETHAndDraw(manager, jug, ethJoin, daiJoin, cdp, wadD);
          
                  emit CDPAction('openLockETHAndDraw', cdp, msg.value, wadD);
              }
          
              function lockGemAndDraw(
                  address manager,
                  address jug,
                  address gemJoin,
                  address daiJoin,
                  uint cdp,
                  uint wadC,
                  uint wadD,
                  bool transferFrom
              ) public {
                  address urn = ManagerLike(manager).urns(cdp);
                  address vat = ManagerLike(manager).vat();
                  bytes32 ilk = ManagerLike(manager).ilks(cdp);
                  // Takes token amount from user's wallet and joins into the vat
                  gemJoin_join(gemJoin, urn, wadC, transferFrom);
                  // Locks token amount into the CDP and generates debt
                  frob(manager, cdp, toInt(convertTo18(gemJoin, wadC)), _getDrawDart(vat, jug, urn, ilk, wadD));
                  // Moves the DAI amount (balance in the vat in rad) to proxy's address
                  move(manager, cdp, address(this), toRad(wadD));
                  // Allows adapter to access to proxy's DAI balance in the vat
                  if (VatLike(vat).can(address(this), address(daiJoin)) == 0) {
                      VatLike(vat).hope(daiJoin);
                  }
                  // Exits DAI to the user's wallet as a token
                  DaiJoinLike(daiJoin).exit(msg.sender, wadD);
          
              }
          
              function openLockGemAndDraw(
                  address manager,
                  address jug,
                  address gemJoin,
                  address daiJoin,
                  bytes32 ilk,
                  uint wadC,
                  uint wadD,
                  bool transferFrom
              ) public returns (uint cdp) {
                  cdp = open(manager, ilk, address(this));
                  lockGemAndDraw(manager, jug, gemJoin, daiJoin, cdp, wadC, wadD, transferFrom);
          
                  emit CDPAction('openLockGemAndDraw', cdp, wadC, wadD);
          
              }
          
              function wipeAllAndFreeETH(
                  address manager,
                  address ethJoin,
                  address daiJoin,
                  uint cdp,
                  uint wadC
              ) public {
                  address vat = ManagerLike(manager).vat();
                  address urn = ManagerLike(manager).urns(cdp);
                  bytes32 ilk = ManagerLike(manager).ilks(cdp);
                  (, uint art) = VatLike(vat).urns(ilk, urn);
          
                  // Joins DAI amount into the vat
                  daiJoin_join(daiJoin, urn, _getWipeAllWad(vat, urn, urn, ilk));
                  // Paybacks debt to the CDP and unlocks WETH amount from it
                  frob(
                      manager,
                      cdp,
                      -toInt(wadC),
                      -int(art)
                  );
                  // Moves the amount from the CDP urn to proxy's address
                  flux(manager, cdp, address(this), wadC);
                  // Exits WETH amount to proxy address as a token
                  GemJoinLike(ethJoin).exit(address(this), wadC);
                  // Converts WETH to ETH
                  GemJoinLike(ethJoin).gem().withdraw(wadC);
                  // Sends ETH back to the user's wallet
                  msg.sender.transfer(wadC);
          
                  emit CDPAction('wipeAllAndFreeETH', cdp, wadC, art);
              }
          
              function wipeAndFreeGem(
                  address manager,
                  address gemJoin,
                  address daiJoin,
                  uint cdp,
                  uint wadC,
                  uint wadD
              ) public {
                  address urn = ManagerLike(manager).urns(cdp);
                  // Joins DAI amount into the vat
                  daiJoin_join(daiJoin, urn, wadD);
                  uint wad18 = convertTo18(gemJoin, wadC);
                  // Paybacks debt to the CDP and unlocks token amount from it
                  frob(
                      manager,
                      cdp,
                      -toInt(wad18),
                      _getWipeDart(ManagerLike(manager).vat(), VatLike(ManagerLike(manager).vat()).dai(urn), urn, ManagerLike(manager).ilks(cdp))
                  );
                  // Moves the amount from the CDP urn to proxy's address
                  flux(manager, cdp, address(this), wad18);
                  // Exits token amount to the user's wallet as a token
                  GemJoinLike(gemJoin).exit(msg.sender, wadC);
              }
          
              function wipeAllAndFreeGem(
                  address manager,
                  address gemJoin,
                  address daiJoin,
                  uint cdp,
                  uint wadC
              ) public {
                  address vat = ManagerLike(manager).vat();
                  address urn = ManagerLike(manager).urns(cdp);
                  bytes32 ilk = ManagerLike(manager).ilks(cdp);
                  (, uint art) = VatLike(vat).urns(ilk, urn);
          
                  // Joins DAI amount into the vat
                  daiJoin_join(daiJoin, urn, _getWipeAllWad(vat, urn, urn, ilk));
                  uint wad18 = convertTo18(gemJoin, wadC);
                  // Paybacks debt to the CDP and unlocks token amount from it
                  frob(
                      manager,
                      cdp,
                      -toInt(wad18),
                      -int(art)
                  );
                  // Moves the amount from the CDP urn to proxy's address
                  flux(manager, cdp, address(this), wad18);
                  // Exits token amount to the user's wallet as a token
                  GemJoinLike(gemJoin).exit(msg.sender, wadC);
          
                  emit CDPAction('wipeAllAndFreeGem', cdp, wadC, art);
              }
          
              function createProxyAndCDP(
                  address manager,
                  address jug,
                  address ethJoin,
                  address daiJoin,
                  bytes32 ilk,
                  uint wadD,
                  address registry
                  ) public payable returns(uint) {
                
                      address proxy = ProxyRegistryInterface(registry).build(msg.sender);
                      
                      uint cdp = openLockETHAndDraw(manager,
                          jug,
                          ethJoin,
                          daiJoin,
                          ilk,
                          wadD
                          );
                      
                      give(manager, cdp, address(proxy));
                      
                      return cdp;
          
              }
          
              function createProxyAndGemCDP(
                  address manager,
                  address jug,
                  address gemJoin,
                  address daiJoin,
                  bytes32 ilk,
                  uint wadC,
                  uint wadD,
                  bool transferFrom,
                  address registry
                  ) public returns(uint) {
                      
          
                      address proxy = ProxyRegistryInterface(registry).build(msg.sender);
                      
                      uint cdp = openLockGemAndDraw(manager,
                          jug,
                          gemJoin,
                          daiJoin,
                          ilk,
                          wadC,
                          wadD,
                          transferFrom);
                      
                      give(manager, cdp, address(proxy));
                      
                      return cdp;
              }
          }