ETH Price: $3,224.73 (+2.76%)

Contract

0x00000000002B13cCcEC913420A21e4D11b2DCd3C
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Recover123780382021-05-06 2:24:551349 days ago1620267895IN
0x00000000...11b2DCd3C
0 ETH0.0040812238.83
Destroy123780262021-05-06 2:23:191349 days ago1620267799IN
0x00000000...11b2DCd3C
0 ETH0.0006557238.83
Deploy75252792019-04-08 4:22:532108 days ago1554697373IN
0x00000000...11b2DCd3C
9.99999999 ETH0.001837744.1
Deploy75252432019-04-08 4:13:562108 days ago1554696836IN
0x00000000...11b2DCd3C
9.99999999 ETH0.001553.1
Destroy75252212019-04-08 4:07:542108 days ago1554696474IN
0x00000000...11b2DCd3C
0 ETH0.00004653.1
Deploy75250772019-04-08 3:37:192108 days ago1554694639IN
0x00000000...11b2DCd3C
1 wei0.000471113.1
Recover75250542019-04-08 3:33:082108 days ago1554694388IN
0x00000000...11b2DCd3C
0 ETH0.000390093.1
Destroy75250272019-04-08 3:28:062108 days ago1554694086IN
0x00000000...11b2DCd3C
0 ETH0.00003152.1
Deploy75249672019-04-08 3:11:402108 days ago1554693100IN
0x00000000...11b2DCd3C
1 wei0.000424452.1

Latest 8 internal transactions

Advanced mode:
Parent Transaction Hash Block
From
To
123780382021-05-06 2:24:551349 days ago1620267895
0x00000000...11b2DCd3C
 Contract Creation0 ETH
75252792019-04-08 4:22:532108 days ago1554697373
0x00000000...11b2DCd3C
 Contract Creation9.99999999 ETH
75250772019-04-08 3:37:192108 days ago1554694639
0x00000000...11b2DCd3C
 Contract Creation1 wei
75250542019-04-08 3:33:082108 days ago1554694388
0x00000000...11b2DCd3C
 Contract Creation0 ETH
75249672019-04-08 3:11:402108 days ago1554693100
0x00000000...11b2DCd3C
 Contract Creation1 wei
75249672019-04-08 3:11:402108 days ago1554693100
0x00000000...11b2DCd3C
 Contract Creation0 ETH
75228432019-04-07 19:14:212109 days ago1554664461
0x00000000...11b2DCd3C
0 ETH
75228432019-04-07 19:14:212109 days ago1554664461  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Metapod

Compiler Version
v0.5.6+commit.b259423e

Optimization Enabled:
Yes with 999 runs

Other Settings:
default evmVersion
/**
 *Submitted for verification at Etherscan.io on 2019-04-07
*/

pragma solidity 0.5.6;


/**
 * @title Metapod (Version 1)
 * @author 0age
 * @notice This contract creates "hardened" metamorphic contracts, or contracts
 * that can be redeployed with new code to the same address, with additional
 * protections against creating non-metamorphic contracts or losing any balance
 * held by the contract when it is destroyed. It does so by first setting the
 * desired contract initialization code in temporary storage. Next, a vault
 * contract corresponding to the target address is checked for a balance, and if
 * one exists it will be sent to the address of an intermediate deployer, or a
 * transient contract with fixed, non-deterministic initialization code. Once
 * deployed via CREATE2, the transient contract retrieves the initialization
 * code from storage and uses it to deploy the contract via CREATE, forwarding
 * the entire balance to the new contract, and then SELFDESTRUCTs. Finally, the
 * contract prelude is checked to ensure that it is properly destructible and
 * that it designates the vault as the forwarding address. Once the contract
 * undergoes metamorphosis, all existing storage will be deleted and any balance
 * will be forwarded to the vault that can then resupply the metamorphic
 * contract upon redeployment.
 * @dev This contract has not yet been fully tested or audited - proceed with
 * abundant caution and please share any exploits or optimizations you discover.
 * Also, bear in mind that any initialization code provided to the contract must
 * contain the proper prelude, or initial sequence, with a length of 44 bytes:
 *
 *  `0x6e2b13cccec913420a21e4d11b2dcd3c3318602b5773 + vault_address + 0xff5b`
 *
 * For the required vault address, use `findVaultContractAddress(bytes32 salt)`.
 * Any initialization code generated by Solidity or another compiler will need
 * to have the stack items provided to JUMP, JUMPI, and CODECOPY altered
 * appropriately upon inserting this code, and may also need to alter some PC
 * operations (especially if it is not Solidity code). Be aware that contracts
 * are still accessible after they have been scheduled for deletion until the
 * transaction is completed, and that ether may still be sent to them - as the
 * funds forwarding step is performed immediately, not as part of the
 * transaction substate with the account removal. If those funds do not move to
 * a non-destructing account by the end of the transaction, they will be
 * irreversibly burned. Lastly, due to the mechanics of SELFDESTRUCT, a contract
 * cannot be destroyed and redeployed in a single transaction - to avoid
 * "downtime" of the contract, consider utilizing multiple contracts and having
 * the callers determine the current contract by using EXTCODEHASH.
 */
contract Metapod {
  // fires when a metamorphic contract is deployed.
  event Metamorphosed(address metamorphicContract, bytes32 salt);

  // fires when a metamorphic contract is destroyed.
  event Cocooned(address metamorphicContract, bytes32 salt);

  // initialization code for transient contract to deploy metamorphic contracts.
  /* ##  op  operation        [stack] <memory> {return_buffer} *contract_deploy*
     00  58  PC               [0]
     01  60  PUSH1 0x1c       [0, 28]
     03  59  MSIZE            [0, 28, 0]
     04  58  PC               [0, 28, 0, 4]
     05  59  MSIZE            [0, 28, 0, 4, 0]
     06  92  SWAP3            [0, 0, 0, 4, 28]
     07  33  CALLER           [0, 0, 0, 4, 28, caller]
     08  5a  GAS              [0, 0, 0, 4, 28, caller, gas]
     09  63  PUSH4 0x57b9f523 [0, 0, 0, 4, 28, caller, gas, selector]
     14  59  MSIZE            [0, 0, 0, 4, 28, caller, gas, selector, 0]
     15  52  MSTORE           [0, 0, 0, 4, 28, caller, gas] <selector>
     16  fa  STATICCALL       [0, 1 => success] {init_code}
     17  50  POP              [0]
     18  60  PUSH1 0x40       [0, 64]
     20  30  ADDRESS          [0, 64, address]
     21  31  BALANCE          [0, 64, balance]
     22  81  DUP2             [0, 64, balance, 64]
     23  3d  RETURNDATASIZE   [0, 64, balance, 64, size]
     24  03  SUB              [0, 64, balance, size - 64]
     25  83  DUP4             [0, 64, balance, size - 64, 0]
     26  92  SWAP3            [0, 0, balance, size - 64, 64]
     27  81  DUP2             [0, 0, balance, size - 64, 64, size - 64]
     28  94  SWAP5            [size - 64, 0, balance, size - 64, 64, 0]
     29  3e  RETURNDATACOPY   [size - 64, 0, balance] <init_code>
     30  f0  CREATE           [contract_address or 0] *init_code*
     31  80  DUP1             [contract_address or 0, contract_address or 0]
     32  15  ISZERO           [contract_address or 0, 0 or 1]
     33  60  PUSH1 0x25       [contract_address or 0, 0 or 1, 37]
     35  57  JUMPI            [contract_address]
     36  ff  SELFDESTRUCT     []
     37  5b  JUMPDEST         [0]
     38  80  DUP1             [0, 0]
     39  fd  REVERT           []
  */
  bytes private constant TRANSIENT_CONTRACT_INITIALIZATION_CODE = (
    hex"58601c59585992335a6357b9f5235952fa5060403031813d03839281943ef08015602557ff5b80fd"
  );

  // store the hash of the initialization code for transient contracts as well.
  bytes32 private constant TRANSIENT_CONTRACT_INITIALIZATION_CODE_HASH = bytes32(
    0xb7d11e258d6663925ce8e43f07ba3b7792a573ecc2fd7682d01f8a70b2223294
  );

  // the "empty data hash" is used to determine if the vault has been deployed.
  bytes32 private constant EMPTY_DATA_HASH = bytes32(
    0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
  );

  // maintain a temporary storage slot for metamorphic initialization code.
  bytes private _initCode;

  constructor() public {
    // ensure that the deployment address is correct.
    // factory: 0x00000000e82eb0431756271F0d00CFB143685e7B
    // caller: 0x0734d56DA60852A03e2Aafae8a36FFd8c12B32f1
    // init code hash: 0x8954ff8965dbf871b7b4f49acc85a2a7c96c93ebc16ba59a4d07c52d8d0b6ec2
    // salt: 0x0734d56da60852a03e2aafae8a36ffd8c12b32f1ee8671f229d5dd0853050000
    require(
      address(this) == address(0x00000000002B13cCcEC913420A21e4D11b2DCd3C),
      "Incorrect deployment address."
    );

    // ensure the transient initialization code hash constant value is correct.
    require(
      keccak256(
        abi.encodePacked(TRANSIENT_CONTRACT_INITIALIZATION_CODE)
      ) == TRANSIENT_CONTRACT_INITIALIZATION_CODE_HASH,
      "Incorrect hash for transient initialization code."
    );

    // ensure the empty data hash constant value is correct.
    require(
      keccak256(abi.encodePacked(hex"")) == EMPTY_DATA_HASH,
      "Incorrect hash for empty data."
    );
  }

  /**
   * @dev Deploy a metamorphic contract by submitting a given salt or nonce
   * along with the initialization code to a transient contract which will then
   * deploy the metamorphic contract before immediately SELFDESTRUCTing. To
   * replace the metamorphic contract, call destroy() with the same salt value,
   * then call with the same salt value and new initialization code (be aware
   * that all existing state will be wiped from the contract).
   * @param identifier uint96 The last twelve bytes of the salt that will be
   * passed into the CREATE2 call (with the first twenty bytes of the salt set
   * to `msg.sender`) and thus will determine the resulant address of the
   * metamorphic contract.
   * @param initializationCode bytes The initialization code for the metamorphic
   * contract that will be deployed by the transient contract.
   * @return The address of the deployed metamorphic contract.
   */
  function deploy(
    uint96 identifier,
    bytes calldata initializationCode
  ) external payable returns (address metamorphicContract) {
    // compute the salt using the supplied identifier.
    bytes32 salt = _getSalt(identifier);

    // store the initialization code to be retrieved by the transient contract.
    _initCode = initializationCode;

    // get vault contract and provide any funds therein to transient contract.
    address vaultContract = _triggerVaultFundsRelease(salt);

    // declare variable to verify successful transient contract deployment.
    address transientContract;

    // move transient contract initialization code into memory.
    bytes memory initCode = TRANSIENT_CONTRACT_INITIALIZATION_CODE;

    // load transient contract init data and size, then deploy via CREATE2.
    assembly { /* solhint-disable no-inline-assembly */
      let encoded_data := add(0x20, initCode) // load initialization code.
      let encoded_size := mload(initCode)     // load the init code's length.
      transientContract := create2(           // call CREATE2 with 4 arguments.
        callvalue,                            // forward any supplied endowment.
        encoded_data,                         // pass in initialization code.
        encoded_size,                         // pass in init code's length.
        salt                                  // pass in the salt value.
      )
    } /* solhint-enable no-inline-assembly */

    // ensure that the contracts were successfully deployed.
    require(transientContract != address(0), "Failed to deploy contract.");

    // get the address of the deployed metamorphic contract.
    metamorphicContract = _getMetamorphicContractAddress(transientContract);

    // ensure that the deployed runtime code has the required prelude.
    _verifyPrelude(metamorphicContract, _getPrelude(vaultContract));

    // clear the supplied initialization code from temporary storage.
    delete _initCode;

    // emit an event to signify that the contract was successfully deployed.
    emit Metamorphosed(metamorphicContract, salt);
  }

  /**
   * @dev Destroy a metamorphic contract by calling into it, which will trigger
   * a SELFDESTRUCT and forward all funds to the designated vault contract. Be
   * aware that all existing state will be wiped from the contract.
   * @param identifier uint96 The last twelve bytes of the salt that was passed
   * into the CREATE2 call (with the first twenty bytes of the salt set to
   * `msg.sender`) that determined resulant address of the metamorphic contract.
   */
  function destroy(uint96 identifier) external {
    // compute the salt using the supplied identifier.
    bytes32 salt = _getSalt(identifier);

    // determine the address of the metamorphic contract.
    address metamorphicContract = _getMetamorphicContractAddress(
      _getTransientContractAddress(salt)
    );

    // call it to trigger a SELFDESTRUCT that forwards any funds to the vault.
    metamorphicContract.call(""); /* solhint-disable-line avoid-low-level-calls */

    // emit an event to signify that the contract was scheduled for deletion.
    emit Cocooned(metamorphicContract, salt);
  }

  /**
   * @dev Recover the funds from a metamorphic contract, the associated vault,
   * and the associated transient contract by deploying a dedicated metamorphic
   * contract that will forward funds to `msg.sender` and immediately
   * SELFDESTRUCT. The contract must be "cocooned" or else it will fail.
   * @param identifier uint96 The last twelve bytes of the salt that was passed
   * into the CREATE2 call (with the first twenty bytes of the salt set to
   * `msg.sender`) that determined resulant address of the metamorphic contract.
   */
  function recover(uint96 identifier) external {
    // compute the salt using the supplied identifier.
    bytes32 salt = _getSalt(identifier);

    // trigger the vault contract to forward funds to the transient contract.
    _triggerVaultFundsRelease(salt);

    // construct recovery contract initialization code and set in temp storage.
    _initCode = abi.encodePacked(
      bytes2(0x5873),  // PC PUSH20
      msg.sender,      // <the caller is the recipient of funds>
      bytes13(0x905959593031856108fcf150ff)
        // SWAP1 MSIZEx3 ADDRESS BALANCE DUP6 PUSH2 2300 CALL POP SELFDESTRUCT
    );

    // declare variable to verify successful transient contract deployment.
    address transientContract;

    // move transient contract initialization code into memory.
    bytes memory initCode = TRANSIENT_CONTRACT_INITIALIZATION_CODE;

    // load transient contract init data and size, then deploy via CREATE2.
    assembly { /* solhint-disable no-inline-assembly */
      let encoded_data := add(0x20, initCode) // load initialization code.
      let encoded_size := mload(initCode)     // load the init code's length.
      transientContract := create2(           // call CREATE2 with 4 arguments.
        callvalue,                            // forward any supplied endowment.
        encoded_data,                         // pass in initialization code.
        encoded_size,                         // pass in init code's length.
        salt                                  // pass in the salt value.
      )
    } /* solhint-enable no-inline-assembly */

    // ensure that the recovery contract was successfully deployed.
    require(
      transientContract != address(0),
      "Recovery failed - ensure that the contract has been destroyed."
    );

    // clear recovery contract initialization code from temporary storage.
    delete _initCode;
  }

  /**
   * @dev View function for retrieving the initialization code for a given
   * metamorphic contract to deploy via a transient contract. Called by the
   * constructor of each transient contract - not meant to be called by users.
   * @return The initialization code to use to deploy the metamorphic contract.
   */
  function getInitializationCode() external view returns (
    bytes memory initializationCode
  ) {
    // return the current initialization code from temporary storage.
    initializationCode = _initCode;
  }

  /**
   * @dev Compute the address of the transient contract that will be created
   * upon submitting a given salt to the contract.
   * @param salt bytes32 The nonce passed into CREATE2 when deploying the
   * transient contract, composed of caller ++ identifier.
   * @return The address of the corresponding transient contract.
   */
  function findTransientContractAddress(
    bytes32 salt
  ) external pure returns (address transientContract) {
    // determine the address where the transient contract will be deployed.
    transientContract = _getTransientContractAddress(salt);
  }

  /**
   * @dev Compute the address of the metamorphic contract that will be created
   * upon submitting a given salt to the contract.
   * @param salt bytes32 The nonce used to create the transient contract that
   * deploys the metamorphic contract, composed of caller ++ identifier.
   * @return The address of the corresponding metamorphic contract.
   */
  function findMetamorphicContractAddress(
    bytes32 salt
  ) external pure returns (address metamorphicContract) {
    // determine the address of the metamorphic contract.
    metamorphicContract = _getMetamorphicContractAddress(
      _getTransientContractAddress(salt)
    );
  }

  /**
   * @dev Compute the address of the vault contract that will be set as the
   * recipient of funds from the metamorphic contract when it is destroyed.
   * @param salt bytes32 The nonce used to create the transient contract that
   * deploys the metamorphic contract, composed of caller ++ identifier.
   * @return The address of the corresponding vault contract.
   */
  function findVaultContractAddress(
    bytes32 salt
  ) external pure returns (address vaultContract) {
    vaultContract = _getVaultContractAddress(
      _getVaultContractInitializationCode(
        _getTransientContractAddress(salt)
      )
    );
  }

  /**
   * @dev View function for retrieving the prelude that will be required for any
   * metamorphic contract deployed via a specific salt.
   * @param salt bytes32 The nonce used to create the transient contract that
   * deploys the metamorphic contract, composed of caller ++ identifier.
   * @return The prelude that will be need to be present at the start of the
   * deployed runtime code for any metamorphic contracts deployed using the
   * provided salt.
   */
  function getPrelude(bytes32 salt) external pure returns (
    bytes memory prelude
  ) {
    // compute and return the prelude.
    prelude = _getPrelude(
      _getVaultContractAddress(
        _getVaultContractInitializationCode(
          _getTransientContractAddress(salt)
        )
      )
    );
  }  

  /**
   * @dev View function for retrieving the initialization code of metamorphic
   * contracts for purposes of verification.
   * @return The initialization code used to deploy transient contracts.
   */
  function getTransientContractInitializationCode() external pure returns (
    bytes memory transientContractInitializationCode
  ) {
    // return the initialization code used to deploy transient contracts.
    transientContractInitializationCode = (
      TRANSIENT_CONTRACT_INITIALIZATION_CODE
    );
  }

  /**
   * @dev View function for retrieving the keccak256 hash of the initialization
   * code of metamorphic contracts for purposes of verification.
   * @return The keccak256 hash of the initialization code used to deploy
   * transient contracts.
   */
  function getTransientContractInitializationCodeHash() external pure returns (
    bytes32 transientContractInitializationCodeHash
  ) {
    // return hash of initialization code used to deploy transient contracts.
    transientContractInitializationCodeHash = (
      TRANSIENT_CONTRACT_INITIALIZATION_CODE_HASH
    );
  }

  /**
   * @dev View function for calculating a salt given a particular caller and
   * identifier.
   * @param identifier bytes12 The last twelve bytes of the salt (the first
   * twenty bytes are set to `msg.sender`).
   * @return The salt that will be supplied to CREATE2 upon providing the given
   * identifier from the calling account.
   */
  function getSalt(uint96 identifier) external view returns (bytes32 salt) {
    salt = _getSalt(identifier);
  }

  /**
   * @dev Internal view function for calculating a salt given a particular
   * caller and identifier.
   * @param identifier bytes12 The last twelve bytes of the salt (the first
   * twenty bytes are set to `msg.sender`).
   * @return The salt that will be supplied to CREATE2.
   */
  function _getSalt(uint96 identifier) internal view returns (bytes32 salt) {
    assembly { /* solhint-disable no-inline-assembly */
      salt := or(shl(96, caller), identifier) // caller: first 20, ID: last 12
    } /* solhint-enable no-inline-assembly */
  }

  /**
   * @dev Internal function for determining the required prelude for metamorphic
   * contracts deployed through the factory based on the corresponding vault
   * contract.
   * @param vaultContract address The address of the vault contract.
   * @return The prelude that will be required for given a vault contract.
   */
  function _getPrelude(
    address vaultContract
  ) internal pure returns (bytes memory prelude) {
    prelude = abi.encodePacked(
      // PUSH15 <this> CALLER XOR PUSH1 43 JUMPI PUSH20
      bytes22(0x6e2b13cccec913420a21e4d11b2dcd3c3318602b5773),
      vaultContract, // <vault is the approved SELFDESTRUCT recipient>
      bytes2(0xff5b) // SELFDESTRUCT JUMPDEST
    );
  }

  /**
   * @dev Internal function for determining if deployed metamorphic contract has
   * the necessary prelude at the start of its runtime code. The prelude ensures
   * that the contract can be destroyed by a call originating from this contract
   * and that any funds will be forwarded to the corresponding vault contract.
   * @param metamorphicContract address The address of the metamorphic contract.
   * @param prelude bytes The prelude that must be present on the contract.
   */
  function _verifyPrelude(
    address metamorphicContract,
    bytes memory prelude
  ) internal view {
    // get the first 44 bytes of metamorphic contract runtime code.
    bytes memory runtimeHeader;

    assembly { /* solhint-disable no-inline-assembly */
      // set and update the pointer based on the size of the runtime header.
      runtimeHeader := mload(0x40)
      mstore(0x40, add(runtimeHeader, 0x60))

      // store the runtime header code and length in memory.
      mstore(runtimeHeader, 44)
      extcodecopy(metamorphicContract, add(runtimeHeader, 0x20), 0, 44)
    } /* solhint-enable no-inline-assembly */

    // ensure that the contract's runtime code has the correct prelude.
    require(
      keccak256(
        abi.encodePacked(prelude)
      ) == keccak256(
        abi.encodePacked(runtimeHeader)
      ),
      "Deployed runtime code does not have the required prelude."
    );
  }

  /**
   * @dev Internal function for determining if a vault contract has a balance
   * and tranferring the balance to the corresponding transient contract if so.
   * This is achieved via deploying the vault contract if no contract exists yet
   * or by calling the contract if it has already been deployed.
   * @param salt bytes32 The nonce used to create the transient contract that
   * deploys the metamorphic contract associated with a corresponding vault.
   * @return The address of the vault contract.
   */
  function _triggerVaultFundsRelease(
    bytes32 salt
  ) internal returns (address vaultContract) {
    // determine the address of the transient contract.
    address transientContract = _getTransientContractAddress(salt);

    // determine the initialization code of the vault contract.
    bytes memory vaultContractInitCode = _getVaultContractInitializationCode(
      transientContract
    );

    // determine the address of the vault contract.
    vaultContract = _getVaultContractAddress(vaultContractInitCode);

    // determine if the vault has a balance.
    if (vaultContract.balance > 0) {
      // determine if the vault has already been deployed.
      bytes32 vaultContractCodeHash;

      assembly { /* solhint-disable no-inline-assembly */
        vaultContractCodeHash := extcodehash(vaultContract)
      } /* solhint-enable no-inline-assembly */

      // if it hasn't been deployed, deploy it to send funds to transient.
      if (vaultContractCodeHash == EMPTY_DATA_HASH) {
        assembly { /* solhint-disable no-inline-assembly */
          let encoded_data := add(0x20, vaultContractInitCode) // init code.
          let encoded_size := mload(vaultContractInitCode)     // init length.
          let _ := create2(                   // call CREATE2.
            0,                                // do not supply any endowment.
            encoded_data,                     // pass in initialization code.
            encoded_size,                     // pass in init code's length.
            0                                 // pass in zero as the salt value.
          )
        } /* solhint-enable no-inline-assembly */
      // otherwise, just call it which will also send funds to transient.
      } else {
        vaultContract.call(""); /* solhint-disable-line avoid-low-level-calls */
      }
    }
  }

  /**
   * @dev Internal view function for calculating a transient contract address
   * given a particular salt.
   * @param salt bytes32 The nonce used to create the transient contract.
   * @return The address of the transient contract.
   */
  function _getTransientContractAddress(
    bytes32 salt
  ) internal pure returns (address transientContract) {
    // determine the address of the transient contract.
    transientContract = address(
      uint160(                      // downcast to match the address type.
        uint256(                    // convert to uint to truncate upper digits.
          keccak256(                // compute the CREATE2 hash using 4 inputs.
            abi.encodePacked(       // pack all inputs to the hash together.
              hex"ff",              // start with 0xff to distinguish from RLP.
              address(0x00000000002B13cCcEC913420A21e4D11b2DCd3C), // this.
              salt,                 // pass in the supplied salt value.
              TRANSIENT_CONTRACT_INITIALIZATION_CODE_HASH // the init code hash.
            )
          )
        )
      )
    );
  }

  /**
   * @dev Internal view function for calculating a metamorphic contract address
   * that has been deployed via a transient contract given the address of the
   * transient contract.
   * @param transientContract address The address of the transient contract.
   * @return The address of the metamorphic contract.
   */
  function _getMetamorphicContractAddress(
    address transientContract
  ) internal pure returns (address metamorphicContract) {
    // determine the address of the metamorphic contract.
    metamorphicContract = address(
      uint160(                          // downcast to match the address type.
        uint256(                        // set to uint to truncate upper digits.
          keccak256(                    // compute CREATE hash via RLP encoding.
            abi.encodePacked(           // pack all inputs to the hash together.
              bytes2(0xd694),           // first two RLP bytes.
              transientContract,        // called by the transient contract.
              byte(0x01)                // nonce begins at 1 for contracts.
            )
          )
        )
      )
    );
  }

  /**
   * @dev Internal view function for calculating a initialization code for a
   * given vault contract based on the corresponding transient contract.
   * @param transientContract address The address of the transient contract.
   * @return The initialization code for the vault contract.
   */
  function _getVaultContractInitializationCode(
    address transientContract
  ) internal pure returns (bytes memory vaultContractInitializationCode) {
    vaultContractInitializationCode = abi.encodePacked(
      // PC PUSH15 <this> CALLER XOR PC JUMPI MSIZEx3 ADDRESS BALANCE PUSH20
      bytes27(0x586e2b13cccec913420a21e4d11b2dcd3c33185857595959303173),
      // the transient contract is the recipient of funds
      transientContract,
      // GAS CALL PUSH1 49 MSIZE DUP2 MSIZEx2 CODECOPY RETURN
      bytes10(0x5af160315981595939f3)
    );
  }

  /**
   * @dev Internal view function for calculating a vault contract address given
   * the initialization code for the vault contract.
   * @param vaultContractInitializationCode bytes The initialization code of the
   * vault contract.
   * @return The address of the vault contract.
   */
  function _getVaultContractAddress(
    bytes memory vaultContractInitializationCode
  ) internal pure returns (address vaultContract) {
    // determine the address of the vault contract.
    vaultContract = address(
      uint160(                      // downcast to match the address type.
        uint256(                    // convert to uint to truncate upper digits.
          keccak256(                // compute the CREATE2 hash using 4 inputs.
            abi.encodePacked(       // pack all inputs to the hash together.
              byte(0xff),           // start with 0xff to distinguish from RLP.
              address(0x00000000002B13cCcEC913420A21e4D11b2DCd3C), // this.
              bytes32(0),           // leave the salt value set to zero.
              keccak256(            // hash the supplied initialization code.
                vaultContractInitializationCode
              )
            )
          )
        )
      )
    );
  }
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[],"name":"getTransientContractInitializationCodeHash","outputs":[{"name":"transientContractInitializationCodeHash","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"getTransientContractInitializationCode","outputs":[{"name":"transientContractInitializationCode","type":"bytes"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"identifier","type":"uint96"}],"name":"getSalt","outputs":[{"name":"salt","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"identifier","type":"uint96"}],"name":"recover","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"identifier","type":"uint96"},{"name":"initializationCode","type":"bytes"}],"name":"deploy","outputs":[{"name":"metamorphicContract","type":"address"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"salt","type":"bytes32"}],"name":"findVaultContractAddress","outputs":[{"name":"vaultContract","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"getInitializationCode","outputs":[{"name":"initializationCode","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"salt","type":"bytes32"}],"name":"findTransientContractAddress","outputs":[{"name":"transientContract","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"salt","type":"bytes32"}],"name":"findMetamorphicContractAddress","outputs":[{"name":"metamorphicContract","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"identifier","type":"uint96"}],"name":"destroy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"salt","type":"bytes32"}],"name":"getPrelude","outputs":[{"name":"prelude","type":"bytes"}],"payable":false,"stateMutability":"pure","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"metamorphicContract","type":"address"},{"indexed":false,"name":"salt","type":"bytes32"}],"name":"Metamorphosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"metamorphicContract","type":"address"},{"indexed":false,"name":"salt","type":"bytes32"}],"name":"Cocooned","type":"event"}]

608060405234801561001057600080fd5b50306e2b13cccec913420a21e4d11b2dcd3c1461008e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f496e636f7272656374206465706c6f796d656e7420616464726573732e000000604482015290519081900360640190fd5b7fb7d11e258d6663925ce8e43f07ba3b7792a573ecc2fd7682d01f8a70b222329460001b604051806060016040528060288152602001611113602891396040516020018082805190602001908083835b602083106100fd5780518252601f1990920191602091820191016100de565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052805190602001201461018e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001806110e26031913960400191505060405180910390fd5b604080516000815260208101918290525190207fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4701461022e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f496e636f7272656374206861736820666f7220656d70747920646174612e0000604482015290519081900360640190fd5b610ea58061023d6000396000f3fe6080604052600436106100bc5760003560e01c80634b7fa04511610074578063b5714de61161004e578063b5714de6146102ee578063e21f6d3014610318578063eaf53a4514610350576100bc565b80634b7fa0451461028557806357b9f523146102af578063a32cfb69146102c4576100bc565b80631215c971116100a55780631215c971146101725780632d2aae91146101aa5780633190a597146101e4576100bc565b8063010fcf85146100c15780630563ef93146100e8575b600080fd5b3480156100cd57600080fd5b506100d661037a565b60408051918252519081900360200190f35b3480156100f457600080fd5b506100fd61039e565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561013757818101518382015260200161011f565b50505050905090810190601f1680156101645780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561017e57600080fd5b506100d66004803603602081101561019557600080fd5b50356bffffffffffffffffffffffff166103be565b3480156101b657600080fd5b506101e2600480360360208110156101cd57600080fd5b50356bffffffffffffffffffffffff166103cf565b005b610269600480360360408110156101fa57600080fd5b6bffffffffffffffffffffffff823516919081019060408101602082013564010000000081111561022a57600080fd5b82018360208201111561023c57600080fd5b8035906020019184600183028401116401000000008311171561025e57600080fd5b509092509050610504565b604080516001600160a01b039092168252519081900360200190f35b34801561029157600080fd5b50610269600480360360208110156102a857600080fd5b5035610646565b3480156102bb57600080fd5b506100fd610661565b3480156102d057600080fd5b50610269600480360360208110156102e757600080fd5b50356106f7565b3480156102fa57600080fd5b506102696004803603602081101561031157600080fd5b5035610702565b34801561032457600080fd5b506101e26004803603602081101561033b57600080fd5b50356bffffffffffffffffffffffff16610715565b34801561035c57600080fd5b506100fd6004803603602081101561037357600080fd5b50356107ca565b7fb7d11e258d6663925ce8e43f07ba3b7792a573ecc2fd7682d01f8a70b222329490565b6060604051806060016040528060288152602001610e5260289139905090565b60006103c9826107e3565b92915050565b60006103da826107e3565b90506103e5816107eb565b50604080517f58730000000000000000000000000000000000000000000000000000000000006020808301919091523360601b60228301527f905959593031856108fcf150ff0000000000000000000000000000000000000060368301528251602381840301815260439092019092528051610465926000920190610c8a565b5060006060604051806060016040528060288152602001610e5260289139905080602001815184818334f5935050506001600160a01b0382166104f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603e815260200180610ddb603e913960400191505060405180910390fd5b6104fe600080610d08565b50505050565b600080610510856107e3565b905061051e60008585610d4f565b50600061052a826107eb565b905060006060604051806060016040528060288152602001610e5260289139905080602001815185818334f5935050506001600160a01b0382166105cf57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4661696c656420746f206465706c6f7920636f6e74726163742e000000000000604482015290519081900360640190fd5b6105d8826108b8565b94506105ec856105e785610939565b6109b0565b6105f7600080610d08565b604080516001600160a01b03871681526020810186905281517fdac6a47173fc05715a5fa4232c433edb0223d14e77705ecee25f76638c4a2ad2929181900390910190a1505050509392505050565b60006103c961065c61065784610aff565b610b9a565b610c11565b60008054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ed5780601f106106c2576101008083540402835291602001916106ed565b820191906000526020600020905b8154815290600101906020018083116106d057829003601f168201915b5050505050905090565b60006103c982610aff565b60006103c961071083610aff565b6108b8565b6000610720826107e3565b9050600061073061071083610aff565b6040519091506001600160a01b03821690600081818181865af19150503d8060008114610779576040519150601f19603f3d011682016040523d82523d6000602084013e61077e565b606091505b5050604080516001600160a01b03841681526020810185905281517f700c3541b523e60eedc9d8483de029723df0e706473f0243434570393f8fb40393509081900390910190a1505050565b60606103c96107de61065c61065785610aff565b610939565b3360601b1790565b6000806107f783610aff565b9050606061080482610b9a565b905061080f81610c11565b92506001600160a01b03831631156108b157823f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081141561086057816020018251600081836000f55050506108af565b6040516001600160a01b03851690600081818181865af19150503d80600081146108a6576040519150601f19603f3d011682016040523d82523d6000602084013e6108ab565b606091505b5050505b505b5050919050565b604080517fd6940000000000000000000000000000000000000000000000000000000000006020808301919091526001600160a01b0390931660601b60228201527f01000000000000000000000000000000000000000000000000000000000000006036820152815160178183030181526037909101909152805191012090565b604080517f6e2b13cccec913420a21e4d11b2dcd3c3318602b57730000000000000000000060208201526001600160a01b0390921660601b60368301527fff5b000000000000000000000000000000000000000000000000000000000000604a8301528051602c818403018152604c909201905290565b6040805160608101909152602c808252600060208301853c806040516020018082805190602001908083835b602083106109fb5780518252601f1990920191602091820191016109dc565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120826040516020018082805190602001908083835b60208310610a695780518252601f199092019160209182019101610a4a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014610afa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526039815260200180610e196039913960400191505060405180910390fd5b505050565b604080517fff000000000000000000000000000000000000000000000000000000000000006020808301919091527a2b13cccec913420a21e4d11b2dcd3c000000000000000000000000602183015260358201939093527fb7d11e258d6663925ce8e43f07ba3b7792a573ecc2fd7682d01f8a70b2223294605580830191909152825180830390910181526075909101909152805191012090565b604080517f586e2b13cccec913420a21e4d11b2dcd3c33185857595959303173000000000060208201526001600160a01b0390921660601b603b8301527f5af160315981595939f300000000000000000000000000000000000000000000604f830152805160398184030181526059909201905290565b8051602091820120604080517fff00000000000000000000000000000000000000000000000000000000000000818501527a2b13cccec913420a21e4d11b2dcd3c000000000000000000000000602182015260006035820152605580820193909352815180820390930183526075019052805191012090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610ccb57805160ff1916838001178555610cf8565b82800160010185558215610cf8579182015b82811115610cf8578251825591602001919060010190610cdd565b50610d04929150610dbd565b5090565b50805460018160011615610100020316600290046000825580601f10610d2e5750610d4c565b601f016020900490600052602060002090810190610d4c9190610dbd565b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610d905782800160ff19823516178555610cf8565b82800160010185558215610cf8579182015b82811115610cf8578235825591602001919060010190610da2565b610dd791905b80821115610d045760008155600101610dc3565b9056fe5265636f76657279206661696c6564202d20656e7375726520746861742074686520636f6e747261637420686173206265656e2064657374726f7965642e4465706c6f7965642072756e74696d6520636f646520646f6573206e6f74206861766520746865207265717569726564207072656c7564652e58601c59585992335a6357b9f5235952fa5060403031813d03839281943ef08015602557ff5b80fda165627a7a723058206411f371afb1521ed97b533674cf320a713eaf657fa9416375ed4d1317700f690029496e636f7272656374206861736820666f72207472616e7369656e7420696e697469616c697a6174696f6e20636f64652e58601c59585992335a6357b9f5235952fa5060403031813d03839281943ef08015602557ff5b80fd

Deployed Bytecode

0x6080604052600436106100bc5760003560e01c80634b7fa04511610074578063b5714de61161004e578063b5714de6146102ee578063e21f6d3014610318578063eaf53a4514610350576100bc565b80634b7fa0451461028557806357b9f523146102af578063a32cfb69146102c4576100bc565b80631215c971116100a55780631215c971146101725780632d2aae91146101aa5780633190a597146101e4576100bc565b8063010fcf85146100c15780630563ef93146100e8575b600080fd5b3480156100cd57600080fd5b506100d661037a565b60408051918252519081900360200190f35b3480156100f457600080fd5b506100fd61039e565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561013757818101518382015260200161011f565b50505050905090810190601f1680156101645780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561017e57600080fd5b506100d66004803603602081101561019557600080fd5b50356bffffffffffffffffffffffff166103be565b3480156101b657600080fd5b506101e2600480360360208110156101cd57600080fd5b50356bffffffffffffffffffffffff166103cf565b005b610269600480360360408110156101fa57600080fd5b6bffffffffffffffffffffffff823516919081019060408101602082013564010000000081111561022a57600080fd5b82018360208201111561023c57600080fd5b8035906020019184600183028401116401000000008311171561025e57600080fd5b509092509050610504565b604080516001600160a01b039092168252519081900360200190f35b34801561029157600080fd5b50610269600480360360208110156102a857600080fd5b5035610646565b3480156102bb57600080fd5b506100fd610661565b3480156102d057600080fd5b50610269600480360360208110156102e757600080fd5b50356106f7565b3480156102fa57600080fd5b506102696004803603602081101561031157600080fd5b5035610702565b34801561032457600080fd5b506101e26004803603602081101561033b57600080fd5b50356bffffffffffffffffffffffff16610715565b34801561035c57600080fd5b506100fd6004803603602081101561037357600080fd5b50356107ca565b7fb7d11e258d6663925ce8e43f07ba3b7792a573ecc2fd7682d01f8a70b222329490565b6060604051806060016040528060288152602001610e5260289139905090565b60006103c9826107e3565b92915050565b60006103da826107e3565b90506103e5816107eb565b50604080517f58730000000000000000000000000000000000000000000000000000000000006020808301919091523360601b60228301527f905959593031856108fcf150ff0000000000000000000000000000000000000060368301528251602381840301815260439092019092528051610465926000920190610c8a565b5060006060604051806060016040528060288152602001610e5260289139905080602001815184818334f5935050506001600160a01b0382166104f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603e815260200180610ddb603e913960400191505060405180910390fd5b6104fe600080610d08565b50505050565b600080610510856107e3565b905061051e60008585610d4f565b50600061052a826107eb565b905060006060604051806060016040528060288152602001610e5260289139905080602001815185818334f5935050506001600160a01b0382166105cf57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f4661696c656420746f206465706c6f7920636f6e74726163742e000000000000604482015290519081900360640190fd5b6105d8826108b8565b94506105ec856105e785610939565b6109b0565b6105f7600080610d08565b604080516001600160a01b03871681526020810186905281517fdac6a47173fc05715a5fa4232c433edb0223d14e77705ecee25f76638c4a2ad2929181900390910190a1505050509392505050565b60006103c961065c61065784610aff565b610b9a565b610c11565b60008054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ed5780601f106106c2576101008083540402835291602001916106ed565b820191906000526020600020905b8154815290600101906020018083116106d057829003601f168201915b5050505050905090565b60006103c982610aff565b60006103c961071083610aff565b6108b8565b6000610720826107e3565b9050600061073061071083610aff565b6040519091506001600160a01b03821690600081818181865af19150503d8060008114610779576040519150601f19603f3d011682016040523d82523d6000602084013e61077e565b606091505b5050604080516001600160a01b03841681526020810185905281517f700c3541b523e60eedc9d8483de029723df0e706473f0243434570393f8fb40393509081900390910190a1505050565b60606103c96107de61065c61065785610aff565b610939565b3360601b1790565b6000806107f783610aff565b9050606061080482610b9a565b905061080f81610c11565b92506001600160a01b03831631156108b157823f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081141561086057816020018251600081836000f55050506108af565b6040516001600160a01b03851690600081818181865af19150503d80600081146108a6576040519150601f19603f3d011682016040523d82523d6000602084013e6108ab565b606091505b5050505b505b5050919050565b604080517fd6940000000000000000000000000000000000000000000000000000000000006020808301919091526001600160a01b0390931660601b60228201527f01000000000000000000000000000000000000000000000000000000000000006036820152815160178183030181526037909101909152805191012090565b604080517f6e2b13cccec913420a21e4d11b2dcd3c3318602b57730000000000000000000060208201526001600160a01b0390921660601b60368301527fff5b000000000000000000000000000000000000000000000000000000000000604a8301528051602c818403018152604c909201905290565b6040805160608101909152602c808252600060208301853c806040516020018082805190602001908083835b602083106109fb5780518252601f1990920191602091820191016109dc565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120826040516020018082805190602001908083835b60208310610a695780518252601f199092019160209182019101610a4a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014610afa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526039815260200180610e196039913960400191505060405180910390fd5b505050565b604080517fff000000000000000000000000000000000000000000000000000000000000006020808301919091527a2b13cccec913420a21e4d11b2dcd3c000000000000000000000000602183015260358201939093527fb7d11e258d6663925ce8e43f07ba3b7792a573ecc2fd7682d01f8a70b2223294605580830191909152825180830390910181526075909101909152805191012090565b604080517f586e2b13cccec913420a21e4d11b2dcd3c33185857595959303173000000000060208201526001600160a01b0390921660601b603b8301527f5af160315981595939f300000000000000000000000000000000000000000000604f830152805160398184030181526059909201905290565b8051602091820120604080517fff00000000000000000000000000000000000000000000000000000000000000818501527a2b13cccec913420a21e4d11b2dcd3c000000000000000000000000602182015260006035820152605580820193909352815180820390930183526075019052805191012090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610ccb57805160ff1916838001178555610cf8565b82800160010185558215610cf8579182015b82811115610cf8578251825591602001919060010190610cdd565b50610d04929150610dbd565b5090565b50805460018160011615610100020316600290046000825580601f10610d2e5750610d4c565b601f016020900490600052602060002090810190610d4c9190610dbd565b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610d905782800160ff19823516178555610cf8565b82800160010185558215610cf8579182015b82811115610cf8578235825591602001919060010190610da2565b610dd791905b80821115610d045760008155600101610dc3565b9056fe5265636f76657279206661696c6564202d20656e7375726520746861742074686520636f6e747261637420686173206265656e2064657374726f7965642e4465706c6f7965642072756e74696d6520636f646520646f6573206e6f74206861766520746865207265717569726564207072656c7564652e58601c59585992335a6357b9f5235952fa5060403031813d03839281943ef08015602557ff5b80fda165627a7a723058206411f371afb1521ed97b533674cf320a713eaf657fa9416375ed4d1317700f690029

Swarm Source

bzzr://6411f371afb1521ed97b533674cf320a713eaf657fa9416375ed4d1317700f69

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.