Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0xb9aaf526 | 20890692 | 82 days ago | IN | 0 ETH | 0.00945617 |
Latest 2 internal transactions
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
20890692 | 82 days ago | Contract Creation | 0 ETH | |||
20840427 | 89 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
UniversalFactory
Compiler Version
v0.8.27+commit.40a35a09
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT /* * Universal Factory Contract * This standard defines an universal factory smart contract where any address (contract or regular account) can * deploy and reserve deterministic contract addresses in any network. * * Written in 2024 by Lohann Paterno Coutinho Ferreira <[email protected]>. * * Universal Factory is derived from EIP-2470 and EIP-3171, with an additional feature that allows the contract * constructor to read arguments without including it in the bytecode, this way custom arguments can be provided * and immutables can be set without influencing the resulting `CREATE2` address. * - EIP-2470: https://eips.ethereum.org/EIPS/eip-2470 * - EIP-3171: https://github.com/ethereum/EIPs/pull/3171 * * This contract is intented to be deployed at the same address on all networks using keyless deployment method. * - Keyless Deployment Method: https://weka.medium.com/how-to-send-ether-to-11-440-people-187e332566b7 * * ██╗ ██╗███╗ ██╗██╗██╗ ██╗███████╗██████╗ ███████╗ █████╗ ██╗ * ██║ ██║████╗ ██║██║██║ ██║██╔════╝██╔══██╗██╔════╝██╔══██╗██║ * ██║ ██║██╔██╗ ██║██║██║ ██║█████╗ ██████╔╝███████╗███████║██║ * ██║ ██║██║╚██╗██║██║╚██╗ ██╔╝██╔══╝ ██╔══██╗╚════██║██╔══██║██║ * ╚██████╔╝██║ ╚████║██║ ╚████╔╝ ███████╗██║ ██║███████║██║ ██║███████╗ * ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝ * ███████╗ █████╗ ██████╗████████╗ ██████╗ ██████╗ ██╗ ██╗ * ██╔════╝██╔══██╗██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗╚██╗ ██╔╝ * █████╗ ███████║██║ ██║ ██║ ██║██████╔╝ ╚████╔╝ * ██╔══╝ ██╔══██║██║ ██║ ██║ ██║██╔══██╗ ╚██╔╝ * ██║ ██║ ██║╚██████╗ ██║ ╚██████╔╝██║ ██║ ██║ * ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ * */ pragma solidity ^0.8.0; /** * @dev The type of create operation being used by the current context. */ enum CreateKind { CREATE2, CREATE3 } /** * @dev Contract Creation Context, this struct is used to provide useful information * to the contract constructor, such as the sender, value, call depth, etc. Without affecting * the final address of the contract. */ struct Context { address contractAddress; address sender; uint8 callDepth; CreateKind kind; bool hasCallback; bytes4 callbackSelector; uint256 value; bytes32 salt; bytes data; } /** * @dev The interface exposed by the Universal Factory Contract. */ interface IUniversalFactory { /** * @dev The create2 `creationCode` reverted. */ error Create2Failed(); /** * @dev The create3 `creationCode` reverted. * obs: Called by `Create3Proxy` using `CREATE` OPCODE. */ error Create3Failed(); /** * @dev The `callback` reverted, this error wraps the revert reason returned by the callback. */ error CallbackFailed(bytes); /** * @dev The deterministic address already exists. */ error ContractAlreadyExists(address); /** * @dev The provided `initCode` is reserved for internal use only, try to use `create3` instead. */ error ReservedInitCode(); /** * @dev Maximum call stack of 127 exceeded. * OBS: probably impossible to reach this limit, due EIP-150 `all but one 64th`. */ error CallStackOverflow(); /** * @dev Emitted when a contract is succesfully created, this is the only event emitted by the * universal factory. */ event ContractCreated( address indexed contractAddress, bytes32 indexed creationCodeHash, bytes32 indexed salt, address indexed sender, bytes32 argumentsHash, bytes32 codeHash, bytes32 callbackHash, uint8 depth, uint256 value ) anonymous; /** * @dev Creates an contract at a deterministic address, the final address is derived from the * `salt` and `creationCode`, and is computed as follow: * ```solidity * return address(uint160(uint256(keccak256(abi.encodePacked(uint8(0xff), address(factory), uint256(salt), keccak256(creationCode)))))); * ``` * The contract constructor can access the actual sender and other information by calling `context()`. * * @param salt Salt of the contract creation, this value affect the resulting address. * @param creationCode Creation code (constructor) of the contract to be deployed, this value affect the resulting address. * @return address of the created contract. */ function create2(bytes32 salt, bytes calldata creationCode) external payable returns (address); /** * @dev Same as `create2(uint256,bytes)`, but also includes `arguments` which will be available at `context.data`. * * @param salt Salt of the contract creation, this value affect the resulting address. * @param creationCode Creation code (constructor) of the contract to be deployed, this value affect the resulting address. * @param arguments data that will be available at `Context.data`, this field doesn't affect the resulting address. * @return address of the created contract. */ function create2(bytes32 salt, bytes calldata creationCode, bytes calldata arguments) external payable returns (address); /** * @dev Same as `create2(uint256,bytes,bytes)`, but also includes a callback used to call the contract after it is created. * @notice The `context.hasCallback` is always set to `true`, this method ALWAYS calls the callback, even if it is empty. * IMPORTANT 1: Throws an `CallbackFailed` error if the callback reverts. * IMPORTANT 2: Funds sent to this method will be forwarded to the `callback`, not the contract constructor. * * @param salt Salt of the contract creation, this value affect the resulting address. * @param creationCode Creation code (constructor) of the contract to be deployed, this value affect the resulting address. * @param arguments data that will be available at `Context.data`, this field doesn't affect the resulting address. * @param callback callback called after create the contract, this field doesn't affect the resulting address. * @return address of the created contract. */ function create2(bytes32 salt, bytes calldata creationCode, bytes calldata arguments, bytes calldata callback) external payable returns (address); /** * Creates an contract at a deterministic address, the final address is derived exclusively from the `salt` field: * ```solidity * salt = keccak256(abi.encodePacked(msg.sender, salt)); * bytes32 proxyHash = 0x0281a97663cf81306691f0800b13a91c4d335e1d772539f127389adae654ffc6; * address proxy = address(uint160(uint256(keccak256(abi.encodePacked(uint8(0xff), address(factory), uint256(salt), proxyHash))))); * return address(uint160(uint256(keccak256(abi.encodePacked(uint16(0xd694), proxy, uint8(1)))))); * ``` * The contract constructor can access the actual sender and other informations by calling `context()`. * * @param salt Salt of the contract creation, resulting address will be derivated from this value only. * @param creationCode Creation code (constructor) of the contract to be deployed, this value doesn't affect the resulting address. * @return address of the created contract. */ function create3(bytes32 salt, bytes calldata creationCode) external payable returns (address); /** * @dev Same as `create3(uint256,bytes)`, but also includes `arguments` which will be available at `context.data`. * * @param salt Salt of the contract creation, this value affect the resulting address. * @param creationCode Creation code (constructor) of the contract to be deployed, this value doesn't affect the resulting address. * @param arguments data that will be available at `Context.data`, this field doesn't affect the resulting address. * @return address of the created contract. */ function create3(bytes32 salt, bytes calldata creationCode, bytes calldata arguments) external payable returns (address); /** * @dev Same as `create3(uint256,bytes,bytes)`, but also includes a callback used to call the contract after it is created. * @notice The `context.hasCallback` is always set to `true`, this method ALWAYS calls the callback, even if it is empty. * IMPORTANT 1: Throws an `CallbackFailed` error if the callback reverts. * IMPORTANT 2: Funds sent to this method will be forwarded to the `callback`, not the contract constructor. * * @param salt Salt of the contract creation, this value affect the resulting address. * @param creationCode Creation code (constructor) of the contract to be deployed, this value doesn't affect the resulting address. * @param arguments data that will be available at `Context.data`, this field doesn't affect the resulting address. * @param callback callback called after create the contract, this field doesn't affect the resulting address. * @return address of the created contract. */ function create3(bytes32 salt, bytes calldata creationCode, bytes calldata arguments, bytes calldata callback) external payable returns (address); /** * @dev Current call context, returns zero for all fields if there's no context. * This function provides useful information that can be accessed inside the contract constructor. * Examples: * - `Context.contractAddress` the address of the contract being created. * - `Context.sender` actual `msg.sender` who called the UniversalFactory. * - `Context.data` to send arguments to the contract constructor without change the resulting address. * - `Context.hasCallback` whether a callback was provided or not. * - `Context.callbackSelector` first 4 bytes of the callback calldata (zero if no callback is provided). * - `Context.callDepth` current call depth, incremented when nested contracts are created. * - `Context.salt` the salt used to derive this contract address. * - `Context.kind` whether `CREATE2` or `CREATE3` is used. * - `Context.value` the value provided, this minimal value between `msg.value` and `address(this).balance` due EVM compatibility. * @return Context current call text, or zero for all values if there's no context. */ function context() external view returns (Context memory); } /** * @title Universal Factory Contract * @author Lohann Paterno Coutinho Ferreira * @notice This contract is a factory that allows you to deploy contracts at deterministic addresses in any network. * * # How it works * To pass arbitrary arguments to the contract without influecing resulting address, this contract caches the arguments * locally, and provide it to the contract constructor when it calls the `context()` function. * - For `cancun` it caches the arguments using the EIP-1153 Transient Storage (~100 gas per word + overhead). * - For `shanghai` it caches the arguments using the regular storage (~2900 gas per word + overhead). * * # Predictable Gas Cost * This contract uses many different Branchless Code techniques (most of them develop by the author), so this contract have an very * predictable gas overhead in any network (the actual overhead may change depending on the EVM implementation). * - For `shanghai` evms, to guarantee an predictable gas cost, it make sure all values stored are different than zero. * This is accomplished by hashing the arguments, and use the resulting hash to XOR the bytes before store and after read it. * - For `cancun` there's no diffence between storing zero or non-zero values, so the `XOR` step is skipped. */ contract UniversalFactory { /** * @notice The Constructor is payable due Frontier EVM compatibility, once that EVM have the concept * of existential deposit (ED), in this evm if you send a balance to a contract without ED, then the * ED will be discounted from the contract balance, as result `address(this).balance < msg.value`, * which is impossible in standard EVM's clients. * - https://github.com/polkadot-evm/frontier/blob/polkadot-v1.11.0/ts-tests/tests/test-balance.ts#L41 * * This contract works correctly in Frontier and standard EVM's, because it forwards the minimum value * between `address(this).balance` and `msg.value` to the created contract. */ constructor() payable { assembly { // Context Storage Layout // | 32-bit | 22-bit | 32-bit | 160-bit | 7-bit | 3-bit | // +-+-+-+-+-+-+-+-+-+-+-+--+-+-+-+-+-+-+-+-+-+-+-++-+-+-+-+-+-+-+-+ // | args | args.len | selector | contract | depth | flags | offset: 0 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | args[..12] (96-bit) | sender (160-bit) | offset: 1 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | salt | offset: 2 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | value | offset: 3 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // | keccak256(args)* | offset: 2**64 * depth // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | args[16..] | offset: 2**64 * depth + 1 // | ... | length: (args.length + 15) / 32 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // // - For `cancun`, the context is stored in `transient storage` using the `TSTORE` and `TLOAD` opcodes. // - For `shanghai`, the context is stored in `regular storage` using the `SSTORE` and `SLOAD` opcodes. // // If the EVM doesn't support EIP-1153 TRANSIENT STORAGE, then it initialize the storage, // because the transition from empty to non-empty cost more gas than the transition // from non-empty to any, example: // - zero to non-zero 20000 gas // - non-zero to non-zero: 2900 gas // - non-zero to zero: 100 gas // // The original values are restored at the end of the execution, except for `args`, which don't need to be restored // once they are stored in an unique offset per call depth. // // # Motivation behind `keccak256(args)`. // Different than `EIP-1153` transient storage, the regular storage is persisted between transactions, so to // guarantee an predictable gas cost, and prevent the previous calls to increase the gas cost of future calls, is // necessary to guarantee that all values stored are different than zero. The way we enforce this is by computing // the keccak256 of `args`, and use it to XOR the bytes before store and after read it, so is infeseable // to create an `argument` that can have 256 consecutive zeros when stored. let placeholder := not(0) sstore(0, placeholder) sstore(1, placeholder) sstore(2, placeholder) sstore(3, placeholder) // Notice is possible to send funds to this contract address before it is deployed. To guarantee this contract // doesn't hold any funds, we sent the whole balance to an `GiveAway` contract, which is deployed below. // GiveAway contract bytecode // 0x34600c573d3d3d3d47335af15b00: // 0x00 0x34 CALLVALUE val // 0x01 0x600c PUSH1 0x0c 12 val // ,=<0x03 0x57 JUMPI // | 0x04 0x3d RETURNDATASIZE 0 // | 0x05 0x3d RETURNDATASIZE 0 0 // | 0x06 0x3d RETURNDATASIZE 0 0 0 // | 0x07 0x3d RETURNDATASIZE 0 0 0 0 // | 0x08 0x47 SELFBALANCE balance 0 0 0 0 // | 0x09 0x33 CALLER addr balance 0 0 0 0 // | 0x0a 0x5a GAS gas addr balance 0 0 0 0 // | 0x0b 0xf1 CALL suc // `=>0x0c 0x5b JUMPDEST suc // 0x0d 0x00 STOP mstore(0x00, 0x6d34600c573d3d3d3d47335af15b003d52600e6012f3) pop(create(selfbalance(), 0x0a, 22)) } } /** * @dev This contract must be compatible with `shanghai` and `cancun` hardforks, the `EIP-1153` opcodes must * only be used when the EVM supports `cancun`, to accomplish that, this contract calls itself and check the * `TLOAD` opcode support, this check is done dynamically in case the EVM supports it in the future. * * @notice inline assembly is used for 3 main reason: * 1. Guarantee the opcode `MCOPY` isn't called, once it is only supported by `cancun`. * 2. Guarantee an predictable gas cost, this contract uses various branchless code techniques develop by the author. * 3. Optimized code, to reduce the gas cost of the contract. * * `Solidity` was chosen over pure `Yul` due portability and developer experience reasons, once currently you can't * import Yul code in Solidity, also in most block explorers you can't verify/publish YUL code. */ fallback() external payable { // ---------------- Static Memory Layout --------------- // offset | description // -------|--------------------------------------------- // 0x0000 | final contract address // 0x0020 | `Create3Proxy` proxy contract address. // 0x0040 | keccak256(creationCode) // 0x0060 | keccak256(arguments) // 0x0080 | keccak256(callback) // 0x00a0 | current depth // 0x00c0 | creationCode.offset // 0x00e0 | creationCode.length // 0x0100 | arguments.offset // 0x0120 | arguments.length // 0x0140 | callback.offset // 0x0160 | callback.length // 0x0180 | previous slot 0 // 0x01a0 | previous slot 1 // 0x01c0 | previous salt // 0x01e0 | previous value // 0x0200 | dynamic memory, ex: creationCode, arguments and callback. // // Obs: the memory layout above is ignored for revert messages. assembly { // If the contracts calls itself, then is for check whether EIP-1153 // transient storage is supported or not. // This check is done dynamically for each call, because even if the EVM // doesn't support this opcode right now, it may support it in the future. if eq(caller(), address()) { mstore(0x00, tload(0)) mstore(0x20, tload(1)) mstore(0x40, tload(2)) mstore(0x60, tload(3)) // obs: for debugging purposes, you can change this to `revert(0,0)` // to disable EIP-1153 support. return(0, 0x80) } // ------- BITFLAGS ------- // HAS_ARGUMENTS = 0x01 // HAS_CALLBACK = 0x02 // IS_CREATE3 = 0x04 // SUPPORT_EIP1153 = 0x08 // ------------------------ let bitflags { { let selector := shr(0xe0, calldataload(0)) /////////////////////////////////////////////////////////////// // function context() external view returns (Context memory) // /////////////////////////////////////////////////////////////// // This selector is checked first to reduce the gas overhead, once this is expected to // be called more frequently. if eq(selector, 0xd0496d6a) { // No value can be sent once it is a view function. It also make sure the call has // sufficient gas, to prevent false negatives when checking for EIP-1153 support. if or(callvalue(), lt(gas(), 3000)) { revert(0, 0) } ////////////////////////// // Load current context // ////////////////////////// // First try to retrieve the context using EIP-1153 TRANSIENT STORAGE, the result // is automatically stored in corresponding static memory. // Obs: This call use all 2000 gas if the EVM doesn't support EIP-1153, and 472 gas // if it supports. We provide an extra gas margin in case those opcodes change their // gas cost in the future. let support_eip1153 := staticcall(2000, address(), 0, 0, 0x0180, 0x80) // if it doesn't support EIP-1153, then load the context from storage. if iszero(support_eip1153) { let slot0 := sload(0) if xor(slot0, not(0)) { mstore(0x0180, slot0) mstore(0x01a0, sload(1)) // Once the `salt` zero is very common, we XOR it with the slot0 to reduce the likelihood // of storing a zero value, otherwise using the salt zero ended up using more gas than // using a non-zero salt, which is inconvenient but not an issue at all. // Notice the previous salt is always restored at the end of the execution. So this value // cannot influence any subsequent contract creation gas cost. mstore(0x01c0, xor(sload(2), slot0)) // Only load the value if the `HAS_VALUE` flag is set. // This flag is used to avoid storing a zero value in the storage, it also saves one storage // write/read when no value is provided (saves ~2900 gas). let has_value := and(slot0, 0x01) if has_value { mstore(0x01e0, sload(3)) } } } // Load context from static memory let slot0 := mload(0x0180) let slot1 := mload(0x01a0) let salt := mload(0x01c0) let value := mload(0x01e0) // Decode `call_flags`. // IS_CREATE3 := 0x04 // HAS_CALLBACK := 0x02 // HAS_VALUE := 0x01 let call_flags := and(slot0, 0x07) let depth := and(shr(3, slot0), 0x7f) let contract_addr := and(shr(10, slot0), 0xffffffffffffffffffffffffffffffffffffffff) let callback_selector := shl(224, shr(170, slot0)) let args_len := and(shr(202, slot0), 0x3fffff) let data := or(shl(160, shr(160, slot1)), shl(128, shr(224, slot0))) let sender := and(slot1, 0xffffffffffffffffffffffffffffffffffffffff) // discard `HAS_VALUE` flag call_flags := shr(1, call_flags) // Store `Context` in memory following Solidity ABI encoding mstore(0x0000, 0x20) // offset mstore(0x0020, contract_addr) // contract_address mstore(0x0040, sender) // sender mstore(0x0060, depth) // call depth mstore(0x0080, shr(1, call_flags)) // kind (0 for CREATE2, 1 for CREATE3) mstore(0x00a0, and(1, call_flags)) // hasCallback mstore(0x00c0, callback_selector) // callbackSelector mstore(0x00e0, value) // value mstore(0x0100, salt) // salt mstore(0x0120, 0x0120) // offset mstore(0x0140, args_len) // data_len mstore(0x0160, data) // arguments[..16] // If the args.length > 16, then copy the rest of the arguments to memory. switch support_eip1153 case 0 { if gt(args_len, 16) { // Copy `data[16..]` from storage to memory for { let end := add(0x0160, args_len) let ptr := 0x170 let offset := shl(64, depth) let args_hash := sload(offset) offset := add(offset, 0x01) } lt(ptr, end) { ptr := add(ptr, 0x20) offset := add(offset, 0x01) } { mstore(ptr, xor(sload(offset), args_hash)) } } } default { // Copy `data[16..]` from transient storage to memory for { let end := add(0x0160, args_len) let ptr := 0x170 let offset := shl(64, depth) } lt(ptr, end) { ptr := add(ptr, 0x20) offset := add(offset, 0x01) } { mstore(ptr, tload(offset)) } } // Remove any non-zero from padding bytes mstore(add(0x0160, args_len), 0) // Return an 32-byte aligned result return(0x00, add(0x0160, and(add(args_len, 0x1f), 0xffffffffffffffe0))) } /////////////////////////// // Validate the selector // /////////////////////////// // The 5 least significant bits of the selectors are unique, this allow an efficient selector // verification using less than 100 gas. // | FUNCTION | SELECTOR | suffix (5-bit) | index | bitflags | // | create2(bytes32,bytes,bytes,bytes) | 0x8778391e | 0x8778391e & 0x1f == 30 | 26 | 011 | // | create3(bytes32,bytes,bytes,bytes) | 0xac049de2 | 0xac049de2 & 0x1f == 2 | 27 | 111 | // | create2(bytes32,bytes,bytes) | 0xce40d339 | 0xce40d339 & 0x1f == 25 | 28 | 001 | // | create3(bytes32,bytes,bytes) | 0xd2a8169a | 0xd2a8169a & 0x1f == 26 | 29 | 101 | // | create2(bytes32,bytes) | 0xb9aaf526 | 0xb9aaf526 & 0x1f == 6 | 30 | 000 | // | create3(bytes32,bytes) | 0x2af25238 | 0x2af25238 & 0x1f == 24 | 31 | 100 | // Convert the 5-bit suffix into an index using byte lookup. let index { let suffix := and(selector, 0x1f) index := byte(suffix, 0x00001b0000001e00000000000000000000000000000000001f1c1d0000001a00) } // Extract the selector at the expected index, where 0x2af25238b9aaf526d2a8169ace40d339ac049de28778391e // is simply the selectors concatenated. let expected_selector { let shift := byte(index, 0x20406080a0) expected_selector := shr(shift, 0x2af25238b9aaf526d2a8169ace40d339ac049de28778391e) expected_selector := and(expected_selector, 0xffffffff) } // Check if the `selector` matches the `expected_selector` let valid := eq(selector, expected_selector) // Validate the calldatasize against the minimal size { let min_calldata_size := byte(index, 0x838363634343) valid := and(valid, gt(calldatasize(), min_calldata_size)) mstore(0x00, sub(min_calldata_size, 4)) } // Revert if the selector is invalid if iszero(valid) { revert(0, 0) } /////////////////////////////// // Load the previous context // /////////////////////////////// // First try to retrieve the context using EIP-1153 TRANSIENT STORAGE, the result is automatically // stored in corresponding static memory. // Obs: This call use all 2000 gas if the EVM doesn't support EIP-1153, and 472 gas if it supports. // We provide an extra gas margin in case those opcodes change their gas cost in the future. let support_eip1153 := staticcall(2000, address(), 0, 0, 0x0180, 0x80) // if it doesn't support EIP-1153, then load the previous context from storage. if iszero(support_eip1153) { let slot0 := sload(0) if xor(slot0, not(0)) { mstore(0x0180, slot0) mstore(0x01a0, sload(1)) mstore(0x01c0, sload(2)) // Only load the value if the `HAS_VALUE` flag is set. // This flag is used to avoid storing a non-zero value in the storage. let has_value := and(slot0, 0x01) if has_value { mstore(0x01e0, sload(3)) } } } // Set the bitflags using byte lookup. // HAS_ARGUMENTS = 0x01 // HAS_CALLBACK = 0x02 // IS_CREATE3 = 0x04 // SUPPORT_EIP1153 = 0x08 bitflags := or(shl(3, support_eip1153), byte(index, 0x030701050004)) } let valid ///////////////////////////// // Validate `creationCode` // ///////////////////////////// let min_calldata_size := mload(0x00) { // creationcode_ptr <= 0xffffffffffffffff let creationcode_ptr := calldataload(0x24) valid := lt(creationcode_ptr, 0x010000000000000000) // creationcode_ptr > min_calldata_size valid := and(valid, gt(creationcode_ptr, min_calldata_size)) // calldatasize > (creationcode_ptr + 0x1f) creationcode_ptr := add(creationcode_ptr, 0x04) valid := and(valid, slt(add(creationcode_ptr, 0x1f), calldatasize())) // creationcode_len <= 0xffffffffffffffff let creationcode_len := calldataload(creationcode_ptr) valid := and(valid, lt(creationcode_len, 0x010000000000000000)) creationcode_ptr := add(creationcode_ptr, 0x20) // (creationcode_ptr + creationcode_len + 0x20) <= calldatasize valid := and(valid, iszero(gt(add(creationcode_ptr, creationcode_len), calldatasize()))) // creationcode_len > 0 valid := and(valid, gt(creationcode_len, 0)) // store the `creationcode_ptr` and `creationcode_len` at static memory 0xc0-0xe0 mstore(0xc0, creationcode_ptr) mstore(0xe0, creationcode_len) } ////////////////////////// // Validate `arguments` // ////////////////////////// { // args_ptr <= 0xffffffffffffffff let args_ptr := calldataload(0x44) let has_args := and(bitflags, 0x01) let valid_args := and(has_args, lt(args_ptr, 0x010000000000000000)) // args_ptr > min_calldata_size valid_args := and(valid_args, gt(args_ptr, min_calldata_size)) // calldatasize > (args_ptr + 0x1f) args_ptr := add(args_ptr, 0x04) valid_args := and(valid_args, slt(add(args_ptr, 0x1f), calldatasize())) // args_len <= 0x3fffff let args_len := calldataload(args_ptr) valid_args := and(valid_args, lt(args_len, 0x400000)) args_ptr := add(args_ptr, 0x20) // (args_ptr + args_len + 0x20) >= calldatasize valid_args := and(valid_args, iszero(gt(add(args_ptr, args_len), calldatasize()))) // Set args_ptr and args_len to zero if there's no arguments valid_args := and(valid_args, has_args) args_ptr := mul(args_ptr, valid_args) args_len := mul(args_len, valid_args) // store the `args_ptr` and `args_len` at static memory 0x0100-0x0120 mstore(0x0100, args_ptr) mstore(0x0120, args_len) // If has no arguments, it is always valid. valid := and(valid, or(valid_args, iszero(has_args))) } ///////////////////////// // Validate `callback` // ///////////////////////// { // callback_ptr <= 0xffffffffffffffff let callback_ptr := calldataload(0x64) let valid_callback := lt(callback_ptr, 0x010000000000000000) // callback_ptr > 0x7f valid_callback := and(valid_callback, gt(callback_ptr, 0x7f)) // calldatasize > (callback_ptr + 0x1f) callback_ptr := add(callback_ptr, 0x04) valid_callback := and(valid_callback, slt(add(callback_ptr, 0x1f), calldatasize())) // callback_len <= 0xffffffffffffffff let callback_len := calldataload(callback_ptr) valid_callback := and(valid_callback, lt(callback_len, 0x010000000000000000)) callback_ptr := add(callback_ptr, 0x20) // (callback_ptr + callback_len + 0x20) >= calldatasize valid_callback := and(valid_callback, iszero(gt(add(callback_ptr, callback_len), calldatasize()))) // Set callback_ptr and callback_len to zero if there's no callback let has_callback := and(shr(1, bitflags), 1) valid_callback := and(valid_callback, has_callback) callback_ptr := mul(callback_ptr, valid_callback) callback_len := mul(callback_len, valid_callback) // store the `callback_ptr` and `callback_len` at static memory 0x0140-0x0160 mstore(0x0140, callback_ptr) mstore(0x0160, callback_len) // If the call has no callback, it is always valid. valid_callback := or(valid_callback, iszero(has_callback)) valid := and(valid, valid_callback) } if iszero(valid) { revert(0, 0) } } /////////////////////////////////////////////////// // Check if the maximum depth of 127 was reached // /////////////////////////////////////////////////// { // Decode the previous `depth`. let slot0 := mload(0x0180) let depth := and(shr(3, slot0), 0x7f) // The `depth` must be less than 127, which is the maximum number of nested calls before overflow. // obs: probably impossible to reach this limit, due EIP-150 `all but one 64th`. // - reference: https://eips.ethereum.org/EIPS/eip-150 if gt(depth, 0x7e) { // revert CallStackOverflow() mstore(0x00, 0x41f739de) revert(0x1c, 0x04) } mstore(0xa0, add(depth, 1)) } // Workaround for Frontier EVM chains, where `address(this).balance` can be less than `msg.value` if // this contract has no previous existential deposit. // - https://github.com/polkadot-evm/frontier/blob/polkadot-v1.11.0/ts-tests/tests/test-balance.ts#L41 // // The following code is a branchless version of the ternary operator, equivalent to: // ```solidity // uint256 value = address(this).balance < msg.value ? address(this).balance : msg.value; // ``` // also see: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/4976 let value := xor(callvalue(), mul(xor(selfbalance(), callvalue()), lt(selfbalance(), callvalue()))) //////////////////////////// // Compute Arguments Hash // //////////////////////////// { let arguments_ptr := mload(0x0100) let arguments_len := mload(0x0120) // Copy `arguments` to memory calldatacopy(0x0200, arguments_ptr, arguments_len) // Compute the keccak256 hash of the `arguments` let arguments_hash := keccak256(0x0200, arguments_len) // Set zero if there's no `arguments`. arguments_hash := mul(arguments_hash, gt(arguments_ptr, 0)) // Save the `arguments_hash` in the static memory mstore(0x60, arguments_hash) } { let addr { // Copy `creationCode` to memory let creationcode_len := mload(0xe0) { let creationcode_ptr := mload(0xc0) calldatacopy(0x0200, creationcode_ptr, creationcode_len) } //////////////////////////////////////////////////////////////////// // Compute CREATE2 address // //////////////////////////////////////////////////////////////////// addr := or(address(), 0xff0000000000000000000000000000000000000000) mstore(0x00, addr) mstore(0x20, calldataload(0x04)) let creationcode_hash := keccak256(0x0200, creationcode_len) mstore(0x40, creationcode_hash) let create2_addr := and(keccak256(11, 85), 0xffffffffffffffffffffffffffffffffffffffff) //////////////////////////////////////////////////////////////////// // Compute CREATE3 address // //////////////////////////////////////////////////////////////////// // Compute `CREATE3` salt, which is `keccak25(abi.encodePacked(msg.sender, salt))` mstore(0x00, caller()) mstore(0x20, calldataload(0x04)) mstore(0x20, keccak256(12, 52)) // Compute `CREATE3` proxy address, which is `keccak256(abi.encodePacked(0xff, address(this), create3salt, proxyHash))` mstore(0x00, addr) let proxy_hash := 0x0281a97663cf81306691f0800b13a91c4d335e1d772539f127389adae654ffc6 mstore(0x40, proxy_hash) let proxy_addr := and(keccak256(11, 85), 0xffffffffffffffffffffffffffffffffffffffff) // Compute `CREATE3` contract address, which is `keccak256(abi.encodePacked(hex"d694", proxyAddr, hex"01"))` mstore(0x00, or(0xd694000000000000000000000000000000000000000001, shl(8, proxy_addr))) let create3_addr := and(keccak256(0x09, 23), 0xffffffffffffffffffffffffffffffffffffffff) ////////////////////// // Validate // ////////////////////// // Validate if the contract exists and if the `creationCode` is not the `Create3Proxy` contract. // // IMPORTANT: The `Create3Proxy` creationCode CANNOT be used in `create2(...)` functions, otherwise // anyone can deploy an contract in a address that belongs to another `msg.sender`. // If someone attempt it, this contract reverts with `ReservedInitCode` error. { let is_create3 := and(shr(2, bitflags), 1) addr := xor(create2_addr, mul(xor(create3_addr, create2_addr), is_create3)) // The proxy creation code is reserved only for `create3` methods let invalid_init_code := and(eq(creationcode_hash, proxy_hash), iszero(is_create3)) // The contract must not exist let contract_exists := extcodesize(addr) if or(contract_exists, invalid_init_code) { // 0xb8bcb0c9 == bytes4(keccak256("ReservedInitCode()")) // 0xc5644373 == bytes4(keccak256("ContractAlreadyExists(address)")) // 0x7dd8f3ba == 0xb8bcb0c9 ^ 0xc5644373 let sig := xor(0xb8bcb0c9, mul(0x7dd8f3ba, invalid_init_code)) let len := add(0x04, shl(5, iszero(invalid_init_code))) mstore(0x00, sig) mstore(0x20, addr) revert(0x1c, len) } } // Store final contract address, proxy address and creationCode in // their respective static memory slots. mstore(0x00, addr) mstore(0x20, proxy_addr) mstore(0x40, creationcode_hash) } //////////////////////////////////////////////////////////////////// // UPDATE CONTEXT // //////////////////////////////////////////////////////////////////// // Context Storage Layout // | 32-bit | 22-bit | 32-bit | 160-bit | 7-bit | 3-bit | // +-+-+-+-+-+-+-+-+-+-+-+--+-+-+-+-+-+-+-+-+-+-+-++-+-+-+-+-+-+-+-+ // | args | args len | selector | contract | depth | flags | offset: 0 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | args[..12] (96-bit) | sender (160-bit) | offset: 1 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | salt | offset: 2 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | value | offset: 3 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // | keccak256(args)* | offset: 2**64 * depth // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // | args[16..] | offset: 2**64 * depth + 1 // | ... | length: (args.length + 15) / 32 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ let arguments_ptr := mload(0x0100) let arguments_len := mload(0x0120) let arguments_data := mul(calldataload(arguments_ptr), gt(arguments_ptr, 0)) let slot0 // Encode `args[12..16]` (32 bits) { let has_args := and(bitflags, 0x01) let args := shr(224, shl(96, arguments_data)) args := mul(args, has_args) slot0 := args } // Encode args_len (22 bits) // Obs: validated previously, so is always less than 2**22 slot0 := or(shl(22, slot0), arguments_len) // Encode selector (32 bits) { let callback_ptr := mload(0x0140) let callback_len := mload(0x0160) let callback_selector := shr(224, calldataload(callback_ptr)) callback_selector := mul(callback_selector, gt(callback_len, 0)) slot0 := or(shl(32, slot0), callback_selector) } // Encode contractAddress (160 bits) slot0 := or(shl(160, slot0), addr) // Encode depth (7 bits) let depth := mload(0xa0) slot0 := or(shl(7, slot0), depth) // Encode bitflags (3 bits) slot0 := or(shl(3, slot0), or(and(bitflags, 0x06), gt(value, 0))) // Encode `args[..12]` (96 bit) + sender (160 bit) let slot1 := or(shl(160, shr(160, arguments_data)), caller()) // Encode salt (256 bits) let salt := calldataload(0x04) // Store the new Context in the transient storage or storage. let support_eip1153 := and(bitflags, 0x08) switch support_eip1153 case 0 { // Store the context in the storage, skip `value` if zero. sstore(0, slot0) sstore(1, slot1) // Once the `salt` zero is very common, we XOR it with the slot0 to reduce the likelihood // of storing a zero value, otherwise using the salt zero ended up using more gas than // using a non-zero salt, which is inconvenient but not an issue at all. // Notice the previous salt is always restored at the end of the execution. So this value // cannot influence any subsequent contract creation gas cost. sstore(2, xor(salt, slot0)) // When `msg.value > 0`, then the first bit of `flags` is set, so no need to store this value (saves ~2900 gas). if value { sstore(3, value) } if gt(arguments_len, 16) { // When `arguments.length > 16`, we also store the argument hash in the context. let arguments_hash := mload(0x60) /// If `args.length > 16`, then store the remaining bytes in the transient storage, // starting at index `2**64 * depth`. for { let end := add(arguments_ptr, arguments_len) let ptr := add(arguments_ptr, 16) let offset := shl(64, depth) sstore(offset, arguments_hash) offset := add(offset, 0x01) } lt(ptr, end) { ptr := add(ptr, 0x20) offset := add(offset, 0x01) } { sstore(offset, xor(calldataload(ptr), arguments_hash)) } } } default { // Store the context in the EIP-1153 Transient Storage. // obs: don't need to skip value once the gas cost is negligible (~100 gas). tstore(0, slot0) tstore(1, slot1) tstore(2, salt) tstore(3, value) // If `data.length > 16`, then store the remaining bytes in the transient storage, // starting at index `2**64 * depth`. for { let end := add(arguments_ptr, arguments_len) let ptr := add(arguments_ptr, 16) let offset := shl(64, depth) } lt(ptr, end) { ptr := add(ptr, 0x20) offset := add(offset, 0x01) } { tstore(offset, calldataload(ptr)) } } } // Create contract using `create2` or `create3` switch and(bitflags, 0x04) case 0 { ///////////////// // CREATE2 // ///////////////// // Deploy contract or Proxy, depending if `is_create3` is enabled. let creationcode_len := mload(0xe0) let contract_addr := create2(mul(value, iszero(and(bitflags, 0x06))), 0x0200, creationcode_len, calldataload(0x04)) // Computed address and actual address must match if or(iszero(contract_addr), xor(contract_addr, mload(0))) { // 0x04a5b3ee -> Create2Failed() mstore(0x00, 0x04a5b3ee) revert(0x1c, 0x04) } } default { ///////////////// // CREATE3 // ///////////////// // Create3Proxy creation code // 0x763318602e57363d3d37363d47f080915215602e57f35bfd602b52336014526460203d3d733d526030601bf3: // 0x00 0x763318602e.. PUSH23 0x3318.. 0x3318602e57363d3d37363d47f080915215602e57f35bfd // 0x18 0x602b PUSH1 0x2b 43 0x3318602e57363d3d37363d47f080915215602e57f35bfd // 0x1a 0x52 MSTORE // 0x1b 0x33 CALLER addr // 0x1c 0x6014 PUSH1 20 20 addr // 0x1f 0x52 MSTORE // 0x25 0x6460203d3d73 PUSH5 0x6020.. 0x60203d3d73 // 0x26 0x3d RETURNDATASIZE 0 0x60203d3d73 // 0x27 0x52 MSTORE // 0x29 0x6030 PUSH1 48 48 // 0x2a 0x601b PUSH1 27 27 48 // 0x2b 0xf3 RETURN // Create3Proxy runtime code, where `XXXX..` is the Universal Factory contract address. // 0x60203d3d73XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX3318602e57363d3d37363d47f080915215602e57f35bfd // 0x00 0x6020 PUSH1 32 32 // 0x02 0x3d RETURNDATASIZE 0 32 // 0x03 0x3d RETURNDATASIZE 0 0 32 // 0x04 0x74XXXXXX.. PUSH20 XXXXXXX factory 0 0 32 // 0x19 0x33 CALLER caller factory 0 0 32 // 0x1a 0x18 XOR invalid 0 0 32 // 0x1b 0x602e PUSH1 0x2e 46 invalid 0 0 32 // ,=< 0x1d 0x57 JUMPI 0 0 32 // | 0x1e 0x36 CALLDATASIZE cls 0 0 32 // | 0x1f 0x3d RETURNDATASIZE 0 cls 0 0 32 // | 0x20 0x3d RETURNDATASIZE 0 0 cls 0 0 32 // | 0x21 0x37 CALLDATACOPY 0 0 32 // | 0x22 0x36 CALLDATASIZE cls 0 0 32 // | 0x23 0x3d RETURNDATASIZE 0 cls 0 0 32 // | 0x24 0x47 SELFBALANCE val 0 cls 0 0 32 // | 0x25 0xf0 CREATE addr 0 0 32 // | 0x26 0x80 DUP1 addr addr 0 0 32 // | 0x27 0x91 SWAP2 0 addr addr 0 32 // | 0x28 0x52 MSTORE addr 0 32 // | 0x29 0x16 ISZERO fail 0 32 // | 0x2a 0x602e PUSH1 0x2e 46 fail 0 32 // |=< 0x2c 0x57 JUMPI 0 32 // | 0x2d 0xf3 RETURN // `=> 0x2e 0x5b JUMPDEST // 0x2f 0xfd REVERT // Deploy the `Create3Proxy` let proxy_addr { // Save the current memory state, to restore it after the proxy deployment. let mem00 := mload(0x00) let mem20 := mload(0x20) { // Compute `CREATE3` salt, which is `keccak25(abi.encodePacked(msg.sender, salt))` mstore(0x00, caller()) mstore(0x20, calldataload(0x04)) let salt := keccak256(12, 52) // Store `Create3Proxy` initcode in memory. mstore(0x0c, 0x60203d3d733d526030601bf3) mstore(0x00, 0x763318602e57363d3d37363d47f080915215602e57f35bfd602b523360145264) proxy_addr := create2(0, 0x00, 44, salt) } // Restore the memory state mstore(0x00, mem00) mstore(0x20, mem20) } // return an error if failed to create `Create3Proxy`. if iszero(and(eq(proxy_addr, mload(0x20)), eq(extcodesize(proxy_addr), 48))) { // revert Create3Failed() mstore(0x00, 0x08fde50a) revert(0x1c, 0x04) } // Save the computed address in the stack // once the `Create3Proxy` will override the 0x00 memory location. let computed_addr := mload(0) // Call the `Create3Proxy` to deploy the desired contract at deterministic address. let creationcode_len := mload(0xe0) // Only send funds if there's no callback let no_callback := iszero(and(bitflags, 0x02)) // Deploy the contract using `Create3Proxy` let success := call(gas(), proxy_addr, mul(value, no_callback), 0x0200, creationcode_len, 0x00, 0x20) // Compare the computed address and actual address if or(iszero(success), xor(computed_addr, mload(0))) { // 0x08fde50a -> Create3Failed() mstore(0x00, 0x08fde50a) revert(0x1c, 0x04) } } // Emit `ContractCreated` event and call `callback` if provided { let callback_ptr := mload(0x140) let callback_len := mload(0x160) { // Compute `keccak256(callback)` let callback_hash // Copy `callback` to memory calldatacopy(0x0200, callback_ptr, callback_len) // Compute callback hash callback_hash := keccak256(0x0200, callback_len) // Set zero if there's no callback callback_hash := mul(callback_hash, gt(callback_ptr, 0)) // emit ContractCreated(contractAddress, creationCodeHash, salt, dataHash, codeHash, callbackHash, depth, value) let creation_code_hash := mload(0x40) let contract_addr := mload(0) let args_hash := mload(0x60) let depth := mload(0xa0) mstore(0x20, args_hash) mstore(0x40, extcodehash(contract_addr)) mstore(0x60, callback_hash) mstore(0x80, depth) mstore(0xa0, value) log4(0x20, 0xa0, contract_addr, creation_code_hash, calldataload(0x04), caller()) // Restore contract addr mstore(0, contract_addr) } // Call `callback` if provided if callback_ptr { if iszero(call(gas(), mload(0), value, 0x0200, callback_len, 0, 0)) { mstore(0x00, 0x30b9b6dd) // error offset mstore(0x20, 0x20) // error length mstore(0x40, returndatasize()) // cleanup padding bytes, in case it has non-zero bytes mstore(add(0x60, returndatasize()), 0x00) // Copy revert data to memory returndatacopy(0x60, 0, returndatasize()) // revert(data + padding) revert(0x1c, add(and(add(returndatasize(), 31), 0xffffffffffffffe0), 0x44)) } } } // Restore previous ctx and salt // Obs: the logic for restore the state is different for storage and transient storage, // because for storage, the `zero to non-zero` transition use more gas than the `non-zero to non-zero`. let prev_slot0 := mload(0x0180) let prev_slot1 := mload(0x01a0) let prev_salt := mload(0x01c0) let prev_value := mload(0x01e0) let support_eip1153 := and(bitflags, 0x08) switch support_eip1153 case 0 { let is_empty := iszero(prev_slot0) let mask := sub(0, is_empty) sstore(0, or(prev_slot0, mask)) sstore(1, or(prev_slot1, mask)) sstore(2, or(prev_salt, mask)) if value { sstore(3, or(prev_value, mask)) } } default { tstore(0, prev_slot0) tstore(1, prev_slot1) tstore(2, prev_salt) tstore(3, prev_value) } // return the created contract address return(0, 0x20) } } }
{ "remappings": [ "forge-std/=lib/forge-std/src/", "@universal-factory/=src/" ], "optimizer": { "enabled": true, "runs": 200000, "details": { "peephole": true, "inliner": true, "deduplicate": false, "cse": true, "yul": true } }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "cancun", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"payable","type":"constructor"},{"stateMutability":"payable","type":"fallback"}]
Contract Creation Code
5f195f555f196001555f196002555f19600355756d34600c573d3d3d3d47335af15b003d52600e6012f35f526016600a47f050610915806100416080396080f3fe3033146108c4575f3560e01c63d0496d6a811461069f577d1b0000001e00000000000000000000000000000000001f1c1d0000001a00601f82161a9065838363634343821a7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc81015f5236119063ffffffff772af25238b9aaf526d2a8169ace40d339ac049de28778391e6420406080a0851a1c1614161561069b576503070105000460806101805f80306107d0fa91821561063e575b1a9060031b175f51906024356004810135916024820160c0528260e0526024604435926001831695600485013594600185368689850101111562400000891083366023870112878711680100000000000000008810861616161616161616809481920102950295856101005286610120526024600160643560048101359088831c9183833687848601011115680100000000000000008410366023870112607f871168010000000000000000881016161616161680958193010261014052026101605216151793881517928115159268010000000000000000366024858501011115931091680100000000000000003660238301129282119110161616161616161561063a57607f6101805160031c16607e811161062d5760010160a052344710344718029182341893808261020037610200209015150260605260e051918260c0516102003774ff0000000000000000000000000000000000000000301790815f526004359384602052610200208060405273ffffffffffffffffffffffffffffffffffffffff6055600b201692335f52856020526034600c206020525f527f0281a97663cf81306691f0800b13a91c4d335e1d772539f127389adae654ffc66040526055600b2074ffffffffffffffffffffffffffffffffffffffff008160081b1676d694000000000000000000000000000000000000000001175f528373ffffffffffffffffffffffffffffffffffffffff60176009201660018760021c1695869118021893157f0281a97663cf81306691f0800b13a91c4d335e1d772539f127389adae654ffc683141680853b1761060f57509073ffffffffffffffffffffffffffffffffffffffff869392855f5216602052604052610100516006610120518215158335029987878c84610140519463ffffffff610160519660a051998a97169b3414158c17971515903560e01c029360801c160260161b1760201b1760a01b1760071b1760031b17997fffffffffffffffffffffffff000000000000000000000000000000000000000033911617600888169a8a8c5f146105aa575090601092915f5d60015d8560025d8960035d830192019060401b905b828110610590575050505b600484161561056a575050505f5190602051335f52836020526034600c206b60203d3d733d526030601bf3600c527f763318602e57363d3d37363d47f080915215602e57f35bfd602b5233601452645f52602c5f80f5925f526030833b14908314161561055d575f602091610200825194600260e0519316158802905af1905f5118901517610550575b81610140516101605190818161020037816102002093604051905f51956060519060a05191602052873f604052841515026060526080528460a05233918660a06020a4835f5261050a575b505050610180516101a051906101c051926101e051945f146104e157505f5d60015d60025d60035d60205ff35b91939281155f038095818094175f5517600155176002556105015760205ff35b1760035560205ff35b6102005f939284935af115610521575f81816104b4565b6330b9b6dd5f52602080523d6040525f3d606001523d5f60603e604467ffffffffffffffe0601f3d011601601cfd5b6308fde50a5f526004601cfd5b6308fde50a5f526004601cfd5b9091925061020060e05191158602f5801591181715610469576304a5b3ee5f526004601cfd5b600191929394508060209135845d019101869392916103d4565b91815f556001558618600255610606575b601081116105cc575b5050506103df565b6001601060605192850194019260401b82815501915b8381106105ef57506105c4565b8035821883558895506001909201916020016105e2565b886003556105bb565b8481637dd8f3ba0263b8bcb0c9185f526020521560051b600401601cfd5b6341f739de5f526004601cfd5b5f80fd5b5f547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811861066e575b506100b6565b806001916101805281546101a0526002546101c0521661068f575b5f610668565b6003546101e052610689565b5f80fd5b610bb85a1034176108c05760806101805f80306107d0fa8015610861575b610180516101a051916101c051926101e05193623fffff8460ca1c169460205f5273ffffffffffffffffffffffffffffffffffffffff85600a1c1660205273ffffffffffffffffffffffffffffffffffffffff8316604052607f8560031c1660605260018560021c16608052600185811c1660a0527fffffffff000000000000000000000000000000000000000000000000000000008560361b1660c05260e05261010052610120805283610140527fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffff000000000000000000000000000000008460601c16911617610160525f1461080557610160820190603d1b687f0000000000000000166101705b8281106107f357505050601f67ffffffffffffffe0915b5f8161016001520116610160015ff35b6020600191835c8152019101906107cc565b60108211610820575b50601f67ffffffffffffffe0916107e3565b603d1b687f0000000000000000168054610160830191600101906101705b83811061084d5750505061080e565b60206001918385541881520192019161083e565b5f547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8118610891575b506106bd565b806001916101805281546101a05280600254186101c052166108b4575b8161088b565b6003546101e0526108ae565b5f80fd5b5f5c5f5260015c60205260025c60405260035c60605260805ff3fea2646970667358221220c08668cd0244953158d248e1677b7e7572d7cbf75dc8e9487789fd51dba84e2d64736f6c634300081b0033
Deployed Bytecode
0x3033146108c4575f3560e01c63d0496d6a811461069f577d1b0000001e00000000000000000000000000000000001f1c1d0000001a00601f82161a9065838363634343821a7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc81015f5236119063ffffffff772af25238b9aaf526d2a8169ace40d339ac049de28778391e6420406080a0851a1c1614161561069b576503070105000460806101805f80306107d0fa91821561063e575b1a9060031b175f51906024356004810135916024820160c0528260e0526024604435926001831695600485013594600185368689850101111562400000891083366023870112878711680100000000000000008810861616161616161616809481920102950295856101005286610120526024600160643560048101359088831c9183833687848601011115680100000000000000008410366023870112607f871168010000000000000000881016161616161680958193010261014052026101605216151793881517928115159268010000000000000000366024858501011115931091680100000000000000003660238301129282119110161616161616161561063a57607f6101805160031c16607e811161062d5760010160a052344710344718029182341893808261020037610200209015150260605260e051918260c0516102003774ff0000000000000000000000000000000000000000301790815f526004359384602052610200208060405273ffffffffffffffffffffffffffffffffffffffff6055600b201692335f52856020526034600c206020525f527f0281a97663cf81306691f0800b13a91c4d335e1d772539f127389adae654ffc66040526055600b2074ffffffffffffffffffffffffffffffffffffffff008160081b1676d694000000000000000000000000000000000000000001175f528373ffffffffffffffffffffffffffffffffffffffff60176009201660018760021c1695869118021893157f0281a97663cf81306691f0800b13a91c4d335e1d772539f127389adae654ffc683141680853b1761060f57509073ffffffffffffffffffffffffffffffffffffffff869392855f5216602052604052610100516006610120518215158335029987878c84610140519463ffffffff610160519660a051998a97169b3414158c17971515903560e01c029360801c160260161b1760201b1760a01b1760071b1760031b17997fffffffffffffffffffffffff000000000000000000000000000000000000000033911617600888169a8a8c5f146105aa575090601092915f5d60015d8560025d8960035d830192019060401b905b828110610590575050505b600484161561056a575050505f5190602051335f52836020526034600c206b60203d3d733d526030601bf3600c527f763318602e57363d3d37363d47f080915215602e57f35bfd602b5233601452645f52602c5f80f5925f526030833b14908314161561055d575f602091610200825194600260e0519316158802905af1905f5118901517610550575b81610140516101605190818161020037816102002093604051905f51956060519060a05191602052873f604052841515026060526080528460a05233918660a06020a4835f5261050a575b505050610180516101a051906101c051926101e051945f146104e157505f5d60015d60025d60035d60205ff35b91939281155f038095818094175f5517600155176002556105015760205ff35b1760035560205ff35b6102005f939284935af115610521575f81816104b4565b6330b9b6dd5f52602080523d6040525f3d606001523d5f60603e604467ffffffffffffffe0601f3d011601601cfd5b6308fde50a5f526004601cfd5b6308fde50a5f526004601cfd5b9091925061020060e05191158602f5801591181715610469576304a5b3ee5f526004601cfd5b600191929394508060209135845d019101869392916103d4565b91815f556001558618600255610606575b601081116105cc575b5050506103df565b6001601060605192850194019260401b82815501915b8381106105ef57506105c4565b8035821883558895506001909201916020016105e2565b886003556105bb565b8481637dd8f3ba0263b8bcb0c9185f526020521560051b600401601cfd5b6341f739de5f526004601cfd5b5f80fd5b5f547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811861066e575b506100b6565b806001916101805281546101a0526002546101c0521661068f575b5f610668565b6003546101e052610689565b5f80fd5b610bb85a1034176108c05760806101805f80306107d0fa8015610861575b610180516101a051916101c051926101e05193623fffff8460ca1c169460205f5273ffffffffffffffffffffffffffffffffffffffff85600a1c1660205273ffffffffffffffffffffffffffffffffffffffff8316604052607f8560031c1660605260018560021c16608052600185811c1660a0527fffffffff000000000000000000000000000000000000000000000000000000008560361b1660c05260e05261010052610120805283610140527fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffff000000000000000000000000000000008460601c16911617610160525f1461080557610160820190603d1b687f0000000000000000166101705b8281106107f357505050601f67ffffffffffffffe0915b5f8161016001520116610160015ff35b6020600191835c8152019101906107cc565b60108211610820575b50601f67ffffffffffffffe0916107e3565b603d1b687f0000000000000000168054610160830191600101906101705b83811061084d5750505061080e565b60206001918385541881520192019161083e565b5f547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8118610891575b506106bd565b806001916101805281546101a05280600254186101c052166108b4575b8161088b565b6003546101e0526108ae565b5f80fd5b5f5c5f5260015c60205260025c60405260035c60605260805ff3fea2646970667358221220c08668cd0244953158d248e1677b7e7572d7cbf75dc8e9487789fd51dba84e2d64736f6c634300081b0033
Deployed Bytecode Sourcemap
20040:40589:0:-:0;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;13070:47567;20040:40589;-1:-1:-1;20040:40589:0;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;13070:47567;20040:40589;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;-1:-1:-1;20040:40589:0;;13070:47567;20040:40589;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;13070:47567;20040:40589;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13070:47567;20040:40589;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;13070:47567;20040:40589;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;-1:-1:-1;20040:40589:0;;-1:-1:-1;20040:40589:0;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;;;;;13070:47567;20040:40589;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;13070:47567;20040:40589;;;;;;;13070:47567;20040:40589;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;-1:-1:-1;20040:40589:0;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;13070:47567;20040:40589;-1:-1:-1;20040:40589:0;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13070:47567;20040:40589;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;-1:-1:-1;20040:40589:0;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;13070:47567;20040:40589;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;13070:47567;20040:40589;;;;;;;;;;;;;13070:47567;20040:40589;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;20040:40589:0;;;;;;;;;;;;;13070:47567;20040:40589;;;;;13070:47567;20040:40589;
Swarm Source
ipfs://c08668cd0244953158d248e1677b7e7572d7cbf75dc8e9487789fd51dba84e2d
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.