pcaversaccio / createx

Factory smart contract to make easier and safer usage of the `CREATE` and `CREATE2` EVM opcodes as well as of `CREATE3`-based (i.e. without an initcode factor) contract creations.
https://createx.rocks
GNU Affero General Public License v3.0
304 stars 18 forks source link

🔥 Add Test Network Deployments #56

Closed pcaversaccio closed 9 months ago

pcaversaccio commented 9 months ago

🕓 Changelog

This PR adds the initial 28 test network deployments. "Harmony Testnet" and "Filecoin Testnet (Calibration)" contract verifications fail due to technical issues on their side, but it's a non-issue since the bytecode is the same as on all other deployed and verified chains, as well as I have verified "Filecoin Testnet (Calibration)" on Sourcify.

Details on "Harmony Testnet" Verification Error

They don't support any API-based verification, and their UI has a parsing bug, disallowing me to verify the contract:

image

Details on "Filecoin Testnet (Calibration)" Verification Error

Their backend verification doesn't support any Solidity version 0.8.23 currently. You can test this via the cURL command:

curl --location --request POST 'https://filfox.info/api/v1/tools/verifyContract' -H 'Content-Type: application/json' -d @./cURL.json

where cURL.json looks like:

{
  "address": "0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed",
  "language": "Solidity",
  "compiler": "latest",
  "optimize": true,
  "optimizeRuns": 10000000,
  "sourceFiles": {
    "src/CreateX.sol": {
      "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.23;\n\n/**\n * @title CreateX Factory Smart Contract\n * @author pcaversaccio (https://web.archive.org/web/20230921103111/https://pcaversaccio.com/)\n * @custom:coauthor Matt Solomon (https://web.archive.org/web/20230921103335/https://mattsolomon.dev/)\n * @notice Factory smart contract to make easier and safer usage of the\n * `CREATE` (https://web.archive.org/web/20230921103540/https://www.evm.codes/#f0?fork=shanghai) and `CREATE2`\n * (https://web.archive.org/web/20230921103540/https://www.evm.codes/#f5?fork=shanghai) EVM opcodes as well as of\n * `CREATE3`-based (https://web.archive.org/web/20230921103920/https://github.com/ethereum/EIPs/pull/3171) contract creations.\n * @dev To simplify testing of non-public variables and functions, we use the `internal`\n * function visibility specifier `internal` for all variables and functions, even though\n * they could technically be `private` since we do not expect anyone to inherit from\n * the `CreateX` contract.\n * @custom:security-contact See https://web.archive.org/web/20230921105029/https://raw.githubusercontent.com/pcaversaccio/createx/main/SECURITY.md.\n */\ncontract CreateX {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         IMMUTABLES                         */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /**\n     * @dev Caches the contract address at construction, to be used for the custom errors.\n     */\n    address internal immutable _SELF = address(this);\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                            TYPES                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /**\n     * @dev Struct for the `payable` amounts in a deploy-and-initialise call.\n     */\n    struct Values {\n        uint256 constructorAmount;\n        uint256 initCallAmount;\n    }\n\n    /**\n     * @dev Enum for the selection of a permissioned deploy protection.\n     */\n    enum SenderBytes {\n        MsgSender,\n        ZeroAddress,\n        Random\n    }\n\n    /**\n     * @dev Enum for the selection of a cross-chain redeploy protection.\n     */\n    enum RedeployProtectionFlag {\n        True,\n        False,\n        Unspecified\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                           EVENTS                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /**\n     * @dev Event that is emitted when a contract is successfully created.\n     * @param newContract The address of the new contract.\n     * @param salt The 32-byte random value used to create the contract address.\n     */\n    event ContractCreation(address indexed newContract, bytes32 indexed salt);\n\n    /**\n     * @dev Event that is emitted when a contract is successfully created.\n     * @param newContract The address of the new contract.\n     */\n    event ContractCreation(address indexed newContract);\n\n    /**\n     * @dev Event that is emitted when a `CREATE3` proxy contract is successfully created.\n     * @param newContract The address of the new proxy contract.\n     * @param salt The 32-byte random value used to create the proxy address.\n     */\n    event Create3ProxyContractCreation(address indexed newContract, bytes32 indexed salt);\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                        CUSTOM ERRORS                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /**\n     * @dev Error that occurs when the contract creation failed.\n     * @param emitter The contract that emits the error.\n     */\n    error FailedContractCreation(address emitter);\n\n    /**\n     * @dev Error that occurs when the contract initialisation call failed.\n     * @param emitter The contract that emits the error.\n     * @param revertData The data returned by the failed initialisation call.\n     */\n    error FailedContractInitialisation(address emitter, bytes revertData);\n\n    /**\n     * @dev Error that occurs when the salt value is invalid.\n     * @param emitter The contract that emits the error.\n     */\n    error InvalidSalt(address emitter);\n\n    /**\n     * @dev Error that occurs when the nonce value is invalid.\n     * @param emitter The contract that emits the error.\n     */\n    error InvalidNonceValue(address emitter);\n\n    /**\n     * @dev Error that occurs when transferring ether has failed.\n     * @param emitter The contract that emits the error.\n     * @param revertData The data returned by the failed ether transfer.\n     */\n    error FailedEtherTransfer(address emitter, bytes revertData);\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                           CREATE                           */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /**\n     * @dev Deploys a new contract via calling the `CREATE` opcode and using the creation\n     * bytecode `initCode` and `msg.value` as inputs. In order to save deployment costs,\n     * we do not sanity check the `initCode` length. Note that if `msg.value` is non-zero,\n     * `initCode` must have a `payable` constructor.\n     * @param initCode The creation bytecode.\n     * @return newContract The 20-byte address where the contract was deployed.\n     */\n    function deployCreate(bytes memory initCode) public payable returns (address newContract) {\n        assembly (\"memory-safe\") {\n            newContract := create(callvalue(), add(initCode, 0x20), mload(initCode))\n        }\n        _requireSuccessfulContractCreation({newContract: newContract});\n        emit ContractCreation({newContract: newContract});\n    }\n\n    /**\n     * @dev Deploys and initialises a new contract via calling the `CREATE` opcode and using the\n     * creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable`\n     * amounts `values`, the refund address `refundAddress`, and `msg.value` as inputs. In order to\n     * save deployment costs, we do not sanity check the `initCode` length. Note that if `values.constructorAmount`\n     * is non-zero, `initCode` must have a `payable` constructor.\n     * @param initCode The creation bytecode.\n     * @param data The initialisation code that is passed to the deployed contract.\n     * @param values The specific `payable` amounts for the deployment and initialisation call.\n     * @param refundAddress The 20-byte address where any excess ether is returned to.\n     * @return newContract The 20-byte address where the contract was deployed.\n     * @custom:security This function allows for reentrancy, however we refrain from adding\n     * a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol\n     * level that potentially malicious reentrant calls do not affect your smart contract system.\n     */\n    function deployCreateAndInit(\n        bytes memory initCode,\n        bytes memory data,\n        Values memory values,\n        address refundAddress\n    ) public payable returns (address newContract) {\n        assembly (\"memory-safe\") {\n            newContract := create(mload(values), add(initCode, 0x20), mload(initCode))\n        }\n        _requireSuccessfulContractCreation({newContract: newContract});\n        emit ContractCreation({newContract: newContract});\n\n        (bool success, bytes memory returnData) = newContract.call{value: values.initCallAmount}(data);\n        if (!success) {\n            revert FailedContractInitialisation({emitter: _SELF, revertData: returnData});\n        }\n\n        if (_SELF.balance != 0) {\n            // Any wei amount previously forced into this contract (e.g. by using the `SELFDESTRUCT`\n            // opcode) will be part of the refund transaction.\n            (success, returnData) = refundAddress.call{value: _SELF.balance}(\"\");\n            if (!success) {\n                revert FailedEtherTransfer({emitter: _SELF, revertData: returnData});\n            }\n        }\n    }\n\n    /**\n     * @dev Deploys and initialises a new contract via calling the `CREATE` opcode and using the\n     * creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable`\n     * amounts `values`, and `msg.value` as inputs. In order to save deployment costs, we do not\n     * sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero,\n     * `initCode` must have a `payable` constructor, and any excess ether is returned to `msg.sender`.\n     * @param initCode The creation bytecode.\n     * @param data The initialisation code that is passed to the deployed contract.\n     * @param values The specific `payable` amounts for the deployment and initialisation call.\n     * @return newContract The 20-byte address where the contract was deployed.\n     * @custom:security This function allows for reentrancy, however we refrain from adding\n     * a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol\n     * level that potentially malicious reentrant calls do not affect your smart contract system.\n     */\n    function deployCreateAndInit(\n        bytes memory initCode,\n        bytes memory data,\n        Values memory values\n    ) public payable returns (address newContract) {\n        newContract = deployCreateAndInit({initCode: initCode, data: data, values: values, refundAddress: msg.sender});\n    }\n\n    /**\n     * @dev Deploys a new EIP-1167 minimal proxy contract using the `CREATE` opcode, and initialises\n     * the implementation contract using the implementation address `implementation`, the initialisation\n     * code `data`, and `msg.value` as inputs. Note that if `msg.value` is non-zero, the initialiser\n     * function called via `data` must be `payable`.\n     * @param implementation The 20-byte implementation contract address.\n     * @param data The initialisation code that is passed to the deployed proxy contract.\n     * @return proxy The 20-byte address where the clone was deployed.\n     * @custom:security This function allows for reentrancy, however we refrain from adding\n     * a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol\n     * level that potentially malicious reentrant calls do not affect your smart contract system.\n     */\n    function deployCreateClone(address implementation, bytes memory data) public payable returns (address proxy) {\n        bytes20 implementationInBytes = bytes20(implementation);\n        assembly (\"memory-safe\") {\n            let clone := mload(0x40)\n            mstore(\n                clone,\n                hex\"3d_60_2d_80_60_0a_3d_39_81_f3_36_3d_3d_37_3d_3d_3d_36_3d_73_00_00_00_00_00_00_00_00_00_00_00_00\"\n            )\n            mstore(add(clone, 0x14), implementationInBytes)\n            mstore(\n                add(clone, 0x28),\n                hex\"5a_f4_3d_82_80_3e_90_3d_91_60_2b_57_fd_5b_f3_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00\"\n            )\n            proxy := create(0, clone, 0x37)\n        }\n        if (proxy == address(0)) {\n            revert FailedContractCreation({emitter: _SELF});\n        }\n        emit ContractCreation({newContract: proxy});\n\n        (bool success, bytes memory returnData) = proxy.call{value: msg.value}(data);\n        _requireSuccessfulContractInitialisation({\n            success: success,\n            returnData: returnData,\n            implementation: implementation\n        });\n    }\n\n    /**\n     * @dev Returns the address where a contract will be stored if deployed via `deployer` using\n     * the `CREATE` opcode. For the specification of the Recursive Length Prefix (RLP) encoding\n     * scheme, please refer to p. 19 of the Ethereum Yellow Paper (https://web.archive.org/web/20230921110603/https://ethereum.github.io/yellowpaper/paper.pdf)\n     * and the Ethereum Wiki (https://web.archive.org/web/20230921112807/https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/).\n     * For further insights also, see the following issue: https://web.archive.org/web/20230921112943/https://github.com/transmissions11/solmate/issues/207.\n     *\n     * Based on the EIP-161 (https://web.archive.org/web/20230921113207/https://raw.githubusercontent.com/ethereum/EIPs/master/EIPS/eip-161.md) specification,\n     * all contract accounts on the Ethereum mainnet are initiated with `nonce = 1`. Thus, the\n     * first contract address created by another contract is calculated with a non-zero nonce.\n     * @param deployer The 20-byte deployer address.\n     * @param nonce The next 32-byte nonce of the deployer address.\n     * @return computedAddress The 20-byte address where a contract will be stored.\n     */\n    function computeCreateAddress(address deployer, uint256 nonce) public view returns (address computedAddress) {\n        bytes memory data;\n        bytes1 len = bytes1(0x94);\n\n        // The theoretical allowed limit, based on EIP-2681, for an account nonce is 2**64-2:\n        // https://web.archive.org/web/20230921113252/https://eips.ethereum.org/EIPS/eip-2681.\n        if (nonce > type(uint64).max - 1) {\n            revert InvalidNonceValue({emitter: _SELF});\n        }\n\n        // The integer zero is treated as an empty byte string and therefore has only one length prefix,\n        // 0x80, which is calculated via 0x80 + 0.\n        if (nonce == 0x00) {\n            data = abi.encodePacked(bytes1(0xd6), len, deployer, bytes1(0x80));\n        }\n        // A one-byte integer in the [0x00, 0x7f] range uses its own value as a length prefix, there is no\n        // additional \"0x80 + length\" prefix that precedes it.\n        else if (nonce <= 0x7f) {\n            data = abi.encodePacked(bytes1(0xd6), len, deployer, uint8(nonce));\n        }\n        // In the case of `nonce > 0x7f` and `nonce <= type(uint8).max`, we have the following encoding scheme\n        // (the same calculation can be carried over for higher nonce bytes):\n        // 0xda = 0xc0 (short RLP prefix) + 0x1a (= the bytes length of: 0x94 + address + 0x84 + nonce, in hex),\n        // 0x94 = 0x80 + 0x14 (= the bytes length of an address, 20 bytes, in hex),\n        // 0x84 = 0x80 + 0x04 (= the bytes length of the nonce, 4 bytes, in hex).\n        else if (nonce <= type(uint8).max) {\n            data = abi.encodePacked(bytes1(0xd7), len, deployer, bytes1(0x81), uint8(nonce));\n        } else if (nonce <= type(uint16).max) {\n            data = abi.encodePacked(bytes1(0xd8), len, deployer, bytes1(0x82), uint16(nonce));\n        } else if (nonce <= type(uint24).max) {\n            data = abi.encodePacked(bytes1(0xd9), len, deployer, bytes1(0x83), uint24(nonce));\n        } else if (nonce <= type(uint32).max) {\n            data = abi.encodePacked(bytes1(0xda), len, deployer, bytes1(0x84), uint32(nonce));\n        } else if (nonce <= type(uint40).max) {\n            data = abi.encodePacked(bytes1(0xdb), len, deployer, bytes1(0x85), uint40(nonce));\n        } else if (nonce <= type(uint48).max) {\n            data = abi.encodePacked(bytes1(0xdc), len, deployer, bytes1(0x86), uint48(nonce));\n        } else if (nonce <= type(uint56).max) {\n            data = abi.encodePacked(bytes1(0xdd), len, deployer, bytes1(0x87), uint56(nonce));\n        } else {\n            data = abi.encodePacked(bytes1(0xde), len, deployer, bytes1(0x88), uint64(nonce));\n        }\n\n        computedAddress = address(uint160(uint256(keccak256(data))));\n    }\n\n    /**\n     * @dev Returns the address where a contract will be stored if deployed via this contract\n     * using the `CREATE` opcode. For the specification of the Recursive Length Prefix (RLP)\n     * encoding scheme, please refer to p. 19 of the Ethereum Yellow Paper (https://web.archive.org/web/20230921110603/https://ethereum.github.io/yellowpaper/paper.pdf)\n     * and the Ethereum Wiki (https://web.archive.org/web/20230921112807/https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/).\n     * For further insights also, see the following issue: https://web.archive.org/web/20230921112943/https://github.com/transmissions11/solmate/issues/207.\n     *\n     * Based on the EIP-161 (https://web.archive.org/web/20230921113207/https://raw.githubusercontent.com/ethereum/EIPs/master/EIPS/eip-161.md) specification,\n     * all contract accounts on the Ethereum mainnet are initiated with `nonce = 1`. Thus, the\n     * first contract address created by another contract is calculated with a non-zero nonce.\n     * @param nonce The next 32-byte nonce of this contract.\n     * @return computedAddress The 20-byte address where a contract will be stored.\n     */\n    function computeCreateAddress(uint256 nonce) public view returns (address computedAddress) {\n        computedAddress = computeCreateAddress({deployer: _SELF, nonce: nonce});\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                           CREATE2                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /**\n     * @dev Deploys a new contract via calling the `CREATE2` opcode and using the salt value `salt`,\n     * the creation bytecode `initCode`, and `msg.value` as inputs. In order to save deployment costs,\n     * we do not sanity check the `initCode` length. Note that if `msg.value` is non-zero, `initCode`\n     * must have a `payable` constructor.\n     * @param salt The 32-byte random value used to create the contract address.\n     * @param initCode The creation bytecode.\n     * @return newContract The 20-byte address where the contract was deployed.\n     */\n    function deployCreate2(bytes32 salt, bytes memory initCode) public payable returns (address newContract) {\n        bytes32 guardedSalt = _guard({salt: salt});\n        assembly (\"memory-safe\") {\n            newContract := create2(callvalue(), add(initCode, 0x20), mload(initCode), guardedSalt)\n        }\n        _requireSuccessfulContractCreation({newContract: newContract});\n        emit ContractCreation({newContract: newContract, salt: guardedSalt});\n    }\n\n    /**\n     * @dev Deploys a new contract via calling the `CREATE2` opcode and using the creation bytecode\n     * `initCode` and `msg.value` as inputs. The salt value is calculated pseudo-randomly using a\n     * diverse selection of block and transaction properties. This approach does not guarantee true\n     * randomness! In order to save deployment costs, we do not sanity check the `initCode` length.\n     * Note that if `msg.value` is non-zero, `initCode` must have a `payable` constructor.\n     * @param initCode The creation bytecode.\n     * @return newContract The 20-byte address where the contract was deployed.\n     */\n    function deployCreate2(bytes memory initCode) public payable returns (address newContract) {\n        // Note that the safeguarding function `_guard` is called as part of the overloaded function\n        // `deployCreate2`.\n        newContract = deployCreate2({salt: _generateSalt(), initCode: initCode});\n    }\n\n    /**\n     * @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the\n     * salt value `salt`, the creation bytecode `initCode`, the initialisation code `data`, the struct\n     * for the `payable` amounts `values`, the refund address `refundAddress`, and `msg.value` as inputs.\n     * In order to save deployment costs, we do not sanity check the `initCode` length. Note that if\n     * `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor.\n     * @param salt The 32-byte random value used to create the contract address.\n     * @param initCode The creation bytecode.\n     * @param data The initialisation code that is passed to the deployed contract.\n     * @param values The specific `payable` amounts for the deployment and initialisation call.\n     * @param refundAddress The 20-byte address where any excess ether is returned to.\n     * @return newContract The 20-byte address where the contract was deployed.\n     * @custom:security This function allows for reentrancy, however we refrain from adding\n     * a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol\n     * level that potentially malicious reentrant calls do not affect your smart contract system.\n     */\n    function deployCreate2AndInit(\n        bytes32 salt,\n        bytes memory initCode,\n        bytes memory data,\n        Values memory values,\n        address refundAddress\n    ) public payable returns (address newContract) {\n        bytes32 guardedSalt = _guard({salt: salt});\n        assembly (\"memory-safe\") {\n            newContract := create2(mload(values), add(initCode, 0x20), mload(initCode), guardedSalt)\n        }\n        _requireSuccessfulContractCreation({newContract: newContract});\n        emit ContractCreation({newContract: newContract, salt: guardedSalt});\n\n        (bool success, bytes memory returnData) = newContract.call{value: values.initCallAmount}(data);\n        if (!success) {\n            revert FailedContractInitialisation({emitter: _SELF, revertData: returnData});\n        }\n\n        if (_SELF.balance != 0) {\n            // Any wei amount previously forced into this contract (e.g. by using the `SELFDESTRUCT`\n            // opcode) will be part of the refund transaction.\n            (success, returnData) = refundAddress.call{value: _SELF.balance}(\"\");\n            if (!success) {\n                revert FailedEtherTransfer({emitter: _SELF, revertData: returnData});\n            }\n        }\n    }\n\n    /**\n     * @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the\n     * salt value `salt`, creation bytecode `initCode`, the initialisation code `data`, the struct for\n     * the `payable` amounts `values`, and `msg.value` as inputs. In order to save deployment costs,\n     * we do not sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero,\n     * `initCode` must have a `payable` constructor, and any excess ether is returned to `msg.sender`.\n     * @param salt The 32-byte random value used to create the contract address.\n     * @param initCode The creation bytecode.\n     * @param data The initialisation code that is passed to the deployed contract.\n     * @param values The specific `payable` amounts for the deployment and initialisation call.\n     * @return newContract The 20-byte address where the contract was deployed.\n     * @custom:security This function allows for reentrancy, however we refrain from adding\n     * a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol\n     * level that potentially malicious reentrant calls do not affect your smart contract system.\n     */\n    function deployCreate2AndInit(\n        bytes32 salt,\n        bytes memory initCode,\n        bytes memory data,\n        Values memory values\n    ) public payable returns (address newContract) {\n        // Note that the safeguarding function `_guard` is called as part of the overloaded function\n        // `deployCreate2AndInit`.\n        newContract = deployCreate2AndInit({\n            salt: salt,\n            initCode: initCode,\n            data: data,\n            values: values,\n            refundAddress: msg.sender\n        });\n    }\n\n    /**\n     * @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the\n     * creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable`\n     * amounts `values`, the refund address `refundAddress`, and `msg.value` as inputs. The salt value\n     * is calculated pseudo-randomly using a diverse selection of block and transaction properties.\n     * This approach does not guarantee true randomness! In order to save deployment costs, we do not\n     * sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero, `initCode`\n     * must have a `payable` constructor.\n     * @param initCode The creation bytecode.\n     * @param data The initialisation code that is passed to the deployed contract.\n     * @param values The specific `payable` amounts for the deployment and initialisation call.\n     * @param refundAddress The 20-byte address where any excess ether is returned to.\n     * @return newContract The 20-byte address where the contract was deployed.\n     * @custom:security This function allows for reentrancy, however we refrain from adding\n     * a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol\n     * level that potentially malicious reentrant calls do not affect your smart contract system.\n     */\n    function deployCreate2AndInit(\n        bytes memory initCode,\n        bytes memory data,\n        Values memory values,\n        address refundAddress\n    ) public payable returns (address newContract) {\n        // Note that the safeguarding function `_guard` is called as part of the overloaded function\n        // `deployCreate2AndInit`.\n        newContract = deployCreate2AndInit({\n            salt: _generateSalt(),\n            initCode: initCode,\n            data: data,\n            values: values,\n            refundAddress: refundAddress\n        });\n    }\n\n    /**\n     * @dev Deploys and initialises a new contract via calling the `CREATE2` opcode and using the\n     * creation bytecode `initCode`, the initialisation code `data`, the struct for the `payable` amounts\n     * `values`, and `msg.value` as inputs. The salt value is calculated pseudo-randomly using a\n     * diverse selection of block and transaction properties. This approach does not guarantee true\n     * randomness! In order to save deployment costs, we do not sanity check the `initCode` length.\n     * Note that if `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor,\n     * and any excess ether is returned to `msg.sender`.\n     * @param initCode The creation bytecode.\n     * @param data The initialisation code that is passed to the deployed contract.\n     * @param values The specific `payable` amounts for the deployment and initialisation call.\n     * @return newContract The 20-byte address where the contract was deployed.\n     * @custom:security This function allows for reentrancy, however we refrain from adding\n     * a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol\n     * level that potentially malicious reentrant calls do not affect your smart contract system.\n     */\n    function deployCreate2AndInit(\n        bytes memory initCode,\n        bytes memory data,\n        Values memory values\n    ) public payable returns (address newContract) {\n        // Note that the safeguarding function `_guard` is called as part of the overloaded function\n        // `deployCreate2AndInit`.\n        newContract = deployCreate2AndInit({\n            salt: _generateSalt(),\n            initCode: initCode,\n            data: data,\n            values: values,\n            refundAddress: msg.sender\n        });\n    }\n\n    /**\n     * @dev Deploys a new EIP-1167 minimal proxy contract using the `CREATE2` opcode and the salt\n     * value `salt`, and initialises the implementation contract using the implementation address\n     * `implementation`, the initialisation code `data`, and `msg.value` as inputs. Note that if\n     * `msg.value` is non-zero, the initialiser function called via `data` must be `payable`.\n     * @param salt The 32-byte random value used to create the proxy contract address.\n     * @param implementation The 20-byte implementation contract address.\n     * @param data The initialisation code that is passed to the deployed proxy contract.\n     * @return proxy The 20-byte address where the clone was deployed.\n     * @custom:security This function allows for reentrancy, however we refrain from adding\n     * a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol\n     * level that potentially malicious reentrant calls do not affect your smart contract system.\n     */\n    function deployCreate2Clone(\n        bytes32 salt,\n        address implementation,\n        bytes memory data\n    ) public payable returns (address proxy) {\n        bytes32 guardedSalt = _guard({salt: salt});\n        bytes20 implementationInBytes = bytes20(implementation);\n        assembly (\"memory-safe\") {\n            let clone := mload(0x40)\n            mstore(\n                clone,\n                hex\"3d_60_2d_80_60_0a_3d_39_81_f3_36_3d_3d_37_3d_3d_3d_36_3d_73_00_00_00_00_00_00_00_00_00_00_00_00\"\n            )\n            mstore(add(clone, 0x14), implementationInBytes)\n            mstore(\n                add(clone, 0x28),\n                hex\"5a_f4_3d_82_80_3e_90_3d_91_60_2b_57_fd_5b_f3_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00\"\n            )\n            proxy := create2(0, clone, 0x37, guardedSalt)\n        }\n        if (proxy == address(0)) {\n            revert FailedContractCreation({emitter: _SELF});\n        }\n        emit ContractCreation({newContract: proxy, salt: guardedSalt});\n\n        (bool success, bytes memory returnData) = proxy.call{value: msg.value}(data);\n        _requireSuccessfulContractInitialisation({\n            success: success,\n            returnData: returnData,\n            implementation: implementation\n        });\n    }\n\n    /**\n     * @dev Deploys a new EIP-1167 minimal proxy contract using the `CREATE2` opcode and the salt\n     * value `salt`, and initialises the implementation contract using the implementation address\n     * `implementation`, the initialisation code `data`, and `msg.value` as inputs. The salt value is\n     * calculated pseudo-randomly using a diverse selection of block and transaction properties. This\n     * approach does not guarantee true randomness! Note that if `msg.value` is non-zero, the initialiser\n     * function called via `data` must be `payable`.\n     * @param implementation The 20-byte implementation contract address.\n     * @param data The initialisation code that is passed to the deployed proxy contract.\n     * @return proxy The 20-byte address where the clone was deployed.\n     * @custom:security This function allows for reentrancy, however we refrain from adding\n     * a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol\n     * level that potentially malicious reentrant calls do not affect your smart contract system.\n     */\n    function deployCreate2Clone(address implementation, bytes memory data) public payable returns (address proxy) {\n        // Note that the safeguarding function `_guard` is called as part of the overloaded function\n        // `deployCreate2Clone`.\n        proxy = deployCreate2Clone({salt: _generateSalt(), implementation: implementation, data: data});\n    }\n\n    /**\n     * @dev Returns the address where a contract will be stored if deployed via `deployer` using\n     * the `CREATE2` opcode. Any change in the `initCodeHash` or `salt` values will result in a new\n     * destination address. This implementation is based on OpenZeppelin:\n     * https://web.archive.org/web/20230921113703/https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/181d518609a9f006fcb97af63e6952e603cf100e/contracts/utils/Create2.sol.\n     * @param salt The 32-byte random value used to create the contract address.\n     * @param initCodeHash The 32-byte bytecode digest of the contract creation bytecode.\n     * @param deployer The 20-byte deployer address.\n     * @return computedAddress The 20-byte address where a contract will be stored.\n     */\n    function computeCreate2Address(\n        bytes32 salt,\n        bytes32 initCodeHash,\n        address deployer\n    ) public pure returns (address computedAddress) {\n        assembly (\"memory-safe\") {\n            // |                      | ↓ ptr ...  ↓ ptr + 0x0B (start) ...  ↓ ptr + 0x20 ...  ↓ ptr + 0x40 ...   |\n            // |----------------------|---------------------------------------------------------------------------|\n            // | initCodeHash         |                                                        CCCCCCCCCCCCC...CC |\n            // | salt                 |                                      BBBBBBBBBBBBB...BB                   |\n            // | deployer             | 000000...0000AAAAAAAAAAAAAAAAAAA...AA                                     |\n            // | 0xFF                 |            FF                                                             |\n            // |----------------------|---------------------------------------------------------------------------|\n            // | memory               | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |\n            // | keccak256(start, 85) |            ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |\n            let ptr := mload(0x40)\n            mstore(add(ptr, 0x40), initCodeHash)\n            mstore(add(ptr, 0x20), salt)\n            mstore(ptr, deployer)\n            let start := add(ptr, 0x0b)\n            mstore8(start, 0xff)\n            computedAddress := keccak256(start, 85)\n        }\n    }\n\n    /**\n     * @dev Returns the address where a contract will be stored if deployed via this contract using\n     * the `CREATE2` opcode. Any change in the `initCodeHash` or `salt` values will result in a new\n     * destination address.\n     * @param salt The 32-byte random value used to create the contract address.\n     * @param initCodeHash The 32-byte bytecode digest of the contract creation bytecode.\n     * @return computedAddress The 20-byte address where a contract will be stored.\n     */\n    function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) public view returns (address computedAddress) {\n        computedAddress = computeCreate2Address({salt: salt, initCodeHash: initCodeHash, deployer: _SELF});\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                           CREATE3                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /**\n     * @dev Deploys a new contract via employing the `CREATE3` pattern (i.e. without an initcode\n     * factor) and using the salt value `salt`, the creation bytecode `initCode`, and `msg.value`\n     * as inputs. In order to save deployment costs, we do not sanity check the `initCode` length.\n     * Note that if `msg.value` is non-zero, `initCode` must have a `payable` constructor. This\n     * implementation is based on Solmate:\n     * https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.\n     * @param salt The 32-byte random value used to create the proxy contract address.\n     * @param initCode The creation bytecode.\n     * @return newContract The 20-byte address where the contract was deployed.\n     * @custom:security We strongly recommend implementing a permissioned deploy protection by setting\n     * the first 20 bytes equal to `msg.sender` in the `salt` to prevent maliciously intended frontrun\n     * proxy deployments on other chains.\n     */\n    function deployCreate3(bytes32 salt, bytes memory initCode) public payable returns (address newContract) {\n        bytes32 guardedSalt = _guard({salt: salt});\n        bytes memory proxyChildBytecode = hex\"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3\";\n        address proxy;\n        assembly (\"memory-safe\") {\n            proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), guardedSalt)\n        }\n        if (proxy == address(0)) {\n            revert FailedContractCreation({emitter: _SELF});\n        }\n        emit Create3ProxyContractCreation({newContract: proxy, salt: guardedSalt});\n\n        newContract = computeCreate3Address({salt: guardedSalt});\n        (bool success, ) = proxy.call{value: msg.value}(initCode);\n        _requireSuccessfulContractCreation({success: success, newContract: newContract});\n        emit ContractCreation({newContract: newContract});\n    }\n\n    /**\n     * @dev Deploys a new contract via employing the `CREATE3` pattern (i.e. without an initcode\n     * factor) and using the salt value `salt`, the creation bytecode `initCode`, and `msg.value`\n     * as inputs. The salt value is calculated pseudo-randomly using a diverse selection of block\n     * and transaction properties. This approach does not guarantee true randomness! In order to save\n     * deployment costs, we do not sanity check the `initCode` length. Note that if `msg.value` is\n     * non-zero, `initCode` must have a `payable` constructor. This implementation is based on Solmate:\n     * https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.\n     * @param initCode The creation bytecode.\n     * @return newContract The 20-byte address where the contract was deployed.\n     */\n    function deployCreate3(bytes memory initCode) public payable returns (address newContract) {\n        // Note that the safeguarding function `_guard` is called as part of the overloaded function\n        // `deployCreate3`.\n        newContract = deployCreate3({salt: _generateSalt(), initCode: initCode});\n    }\n\n    /**\n     * @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without\n     * an initcode factor) and using the salt value `salt`, the creation bytecode `initCode`, the\n     * initialisation code `data`, the struct for the `payable` amounts `values`, the refund address\n     * `refundAddress`, and `msg.value` as inputs. In order to save deployment costs, we do not sanity\n     * check the `initCode` length. Note that if `values.constructorAmount` is non-zero, `initCode` must\n     * have a `payable` constructor. This implementation is based on Solmate:\n     * https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.\n     * @param salt The 32-byte random value used to create the proxy contract address.\n     * @param initCode The creation bytecode.\n     * @param data The initialisation code that is passed to the deployed contract.\n     * @param values The specific `payable` amounts for the deployment and initialisation call.\n     * @param refundAddress The 20-byte address where any excess ether is returned to.\n     * @return newContract The 20-byte address where the contract was deployed.\n     * @custom:security This function allows for reentrancy, however we refrain from adding\n     * a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol\n     * level that potentially malicious reentrant calls do not affect your smart contract system.\n     * Furthermore, we strongly recommend implementing a permissioned deploy protection by setting\n     * the first 20 bytes equal to `msg.sender` in the `salt` to prevent maliciously intended frontrun\n     * proxy deployments on other chains.\n     */\n    function deployCreate3AndInit(\n        bytes32 salt,\n        bytes memory initCode,\n        bytes memory data,\n        Values memory values,\n        address refundAddress\n    ) public payable returns (address newContract) {\n        bytes32 guardedSalt = _guard({salt: salt});\n        bytes memory proxyChildBytecode = hex\"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3\";\n        address proxy;\n        assembly (\"memory-safe\") {\n            proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), guardedSalt)\n        }\n        if (proxy == address(0)) {\n            revert FailedContractCreation({emitter: _SELF});\n        }\n        emit Create3ProxyContractCreation({newContract: proxy, salt: guardedSalt});\n\n        newContract = computeCreate3Address({salt: guardedSalt});\n        (bool success, ) = proxy.call{value: values.constructorAmount}(initCode);\n        _requireSuccessfulContractCreation({success: success, newContract: newContract});\n        emit ContractCreation({newContract: newContract});\n\n        bytes memory returnData;\n        (success, returnData) = newContract.call{value: values.initCallAmount}(data);\n        if (!success) {\n            revert FailedContractInitialisation({emitter: _SELF, revertData: returnData});\n        }\n\n        if (_SELF.balance != 0) {\n            // Any wei amount previously forced into this contract (e.g. by using the `SELFDESTRUCT`\n            // opcode) will be part of the refund transaction.\n            (success, returnData) = refundAddress.call{value: _SELF.balance}(\"\");\n            if (!success) {\n                revert FailedEtherTransfer({emitter: _SELF, revertData: returnData});\n            }\n        }\n    }\n\n    /**\n     * @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without\n     * an initcode factor) and using the salt value `salt`, the creation bytecode `initCode`, the\n     * initialisation code `data`, the struct for the `payable` amounts `values`, and `msg.value` as\n     * inputs. In order to save deployment costs, we do not sanity check the `initCode` length. Note\n     * that if `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor,\n     * and any excess ether is returned to `msg.sender`. This implementation is based on Solmate:\n     * https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.\n     * @param salt The 32-byte random value used to create the proxy contract address.\n     * @param initCode The creation bytecode.\n     * @param data The initialisation code that is passed to the deployed contract.\n     * @param values The specific `payable` amounts for the deployment and initialisation call.\n     * @return newContract The 20-byte address where the contract was deployed.\n     * @custom:security This function allows for reentrancy, however we refrain from adding\n     * a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol\n     * level that potentially malicious reentrant calls do not affect your smart contract system.\n     * Furthermore, we strongly recommend implementing a permissioned deploy protection by setting\n     * the first 20 bytes equal to `msg.sender` in the `salt` to prevent maliciously intended frontrun\n     * proxy deployments on other chains.\n     */\n    function deployCreate3AndInit(\n        bytes32 salt,\n        bytes memory initCode,\n        bytes memory data,\n        Values memory values\n    ) public payable returns (address newContract) {\n        // Note that the safeguarding function `_guard` is called as part of the overloaded function\n        // `deployCreate3AndInit`.\n        newContract = deployCreate3AndInit({\n            salt: salt,\n            initCode: initCode,\n            data: data,\n            values: values,\n            refundAddress: msg.sender\n        });\n    }\n\n    /**\n     * @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without\n     * an initcode factor) and using the creation bytecode `initCode`, the initialisation code `data`,\n     * the struct for the `payable` amounts `values`, the refund address `refundAddress`, and `msg.value`\n     * as inputs. The salt value is calculated pseudo-randomly using a diverse selection of block and\n     * transaction properties. This approach does not guarantee true randomness! In order to save deployment\n     * costs, we do not sanity check the `initCode` length. Note that if `values.constructorAmount` is non-zero,\n     * `initCode` must have a `payable` constructor. This implementation is based on Solmate:\n     * https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.\n     * @param initCode The creation bytecode.\n     * @param data The initialisation code that is passed to the deployed contract.\n     * @param values The specific `payable` amounts for the deployment and initialisation call.\n     * @param refundAddress The 20-byte address where any excess ether is returned to.\n     * @return newContract The 20-byte address where the contract was deployed.\n     * @custom:security This function allows for reentrancy, however we refrain from adding\n     * a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol\n     * level that potentially malicious reentrant calls do not affect your smart contract system.\n     */\n    function deployCreate3AndInit(\n        bytes memory initCode,\n        bytes memory data,\n        Values memory values,\n        address refundAddress\n    ) public payable returns (address newContract) {\n        // Note that the safeguarding function `_guard` is called as part of the overloaded function\n        // `deployCreate3AndInit`.\n        newContract = deployCreate3AndInit({\n            salt: _generateSalt(),\n            initCode: initCode,\n            data: data,\n            values: values,\n            refundAddress: refundAddress\n        });\n    }\n\n    /**\n     * @dev Deploys and initialises a new contract via employing the `CREATE3` pattern (i.e. without\n     * an initcode factor) and using the creation bytecode `initCode`, the initialisation code `data`,\n     * the struct for the `payable` amounts `values`, `msg.value` as inputs. The salt value is calculated\n     * pseudo-randomly using a diverse selection of block and transaction properties. This approach does\n     * not guarantee true randomness! In order to save deployment costs, we do not sanity check the `initCode`\n     * length. Note that if `values.constructorAmount` is non-zero, `initCode` must have a `payable` constructor,\n     * and any excess ether is returned to `msg.sender`. This implementation is based on Solmate:\n     * https://web.archive.org/web/20230921113832/https://raw.githubusercontent.com/transmissions11/solmate/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol.\n     * @param initCode The creation bytecode.\n     * @param data The initialisation code that is passed to the deployed contract.\n     * @param values The specific `payable` amounts for the deployment and initialisation call.\n     * @return newContract The 20-byte address where the contract was deployed.\n     * @custom:security This function allows for reentrancy, however we refrain from adding\n     * a mutex lock to keep it as use-case agnostic as possible. Please ensure at the protocol\n     * level that potentially malicious reentrant calls do not affect your smart contract system.\n     */\n    function deployCreate3AndInit(\n        bytes memory initCode,\n        bytes memory data,\n        Values memory values\n    ) public payable returns (address newContract) {\n        // Note that the safeguarding function `_guard` is called as part of the overloaded function\n        // `deployCreate3AndInit`.\n        newContract = deployCreate3AndInit({\n            salt: _generateSalt(),\n            initCode: initCode,\n            data: data,\n            values: values,\n            refundAddress: msg.sender\n        });\n    }\n\n    /**\n     * @dev Returns the address where a contract will be stored if deployed via `deployer` using\n     * the `CREATE3` pattern (i.e. without an initcode factor). Any change in the `salt` value will\n     * result in a new destination address. This implementation is based on Solady:\n     * https://web.archive.org/web/20230921114120/https://raw.githubusercontent.com/Vectorized/solady/1c1ac4ad9c8558001e92d8d1a7722ef67bec75df/src/utils/CREATE3.sol.\n     * @param salt The 32-byte random value used to create the proxy contract address.\n     * @param deployer The 20-byte deployer address.\n     * @return computedAddress The 20-byte address where a contract will be stored.\n     */\n    function computeCreate3Address(bytes32 salt, address deployer) public pure returns (address computedAddress) {\n        assembly (\"memory-safe\") {\n            let ptr := mload(0x40)\n            mstore(0x00, deployer)\n            mstore8(0x0b, 0xff)\n            mstore(0x20, salt)\n            mstore(\n                0x40,\n                hex\"21_c3_5d_be_1b_34_4a_24_88_cf_33_21_d6_ce_54_2f_8e_9f_30_55_44_ff_09_e4_99_3a_62_31_9a_49_7c_1f\"\n            )\n            mstore(0x14, keccak256(0x0b, 0x55))\n            mstore(0x40, ptr)\n            mstore(0x00, 0xd694)\n            mstore8(0x34, 0x01)\n            computedAddress := keccak256(0x1e, 0x17)\n        }\n    }\n\n    /**\n     * @dev Returns the address where a contract will be stored if deployed via this contract using\n     * the `CREATE3` pattern (i.e. without an initcode factor). Any change in the `salt` value will\n     * result in a new destination address. This implementation is based on Solady:\n     * https://web.archive.org/web/20230921114120/https://raw.githubusercontent.com/Vectorized/solady/1c1ac4ad9c8558001e92d8d1a7722ef67bec75df/src/utils/CREATE3.sol.\n     * @param salt The 32-byte random value used to create the proxy contract address.\n     * @return computedAddress The 20-byte address where a contract will be stored.\n     */\n    function computeCreate3Address(bytes32 salt) public view returns (address computedAddress) {\n        computedAddress = computeCreate3Address({salt: salt, deployer: _SELF});\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                      HELPER FUNCTIONS                      */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /**\n     * @dev Implements different safeguarding mechanisms depending on the encoded values in the salt\n     * (`||` stands for byte-wise concatenation):\n     *   => salt (32 bytes) = 0xbebebebebebebebebebebebebebebebebebebebe||ff||1212121212121212121212\n     *   - The first 20 bytes (i.e. `bebebebebebebebebebebebebebebebebebebebe`) may be used to\n     *     implement a permissioned deploy protection by setting them equal to `msg.sender`,\n     *   - The 21st byte (i.e. `ff`) may be used to implement a cross-chain redeploy protection by\n     *     setting it equal to `0x01`,\n     *   - The last random 11 bytes (i.e. `1212121212121212121212`) allow for 2**88 bits of entropy\n     *     for mining a salt.\n     * @param salt The 32-byte random value used to create the contract address.\n     * @return guardedSalt The guarded 32-byte random value used to create the contract address.\n     */\n    function _guard(bytes32 salt) internal view returns (bytes32 guardedSalt) {\n        (SenderBytes senderBytes, RedeployProtectionFlag redeployProtectionFlag) = _parseSalt({salt: salt});\n\n        if (senderBytes == SenderBytes.MsgSender && redeployProtectionFlag == RedeployProtectionFlag.True) {\n            // Configures a permissioned deploy protection as well as a cross-chain redeploy protection.\n            guardedSalt = keccak256(abi.encode(msg.sender, block.chainid, salt));\n        } else if (senderBytes == SenderBytes.MsgSender && redeployProtectionFlag == RedeployProtectionFlag.False) {\n            // Configures solely a permissioned deploy protection.\n            guardedSalt = _efficientHash({a: bytes32(uint256(uint160(msg.sender))), b: salt});\n        } else if (senderBytes == SenderBytes.MsgSender) {\n            // Reverts if the 21st byte is greater than `0x01` in order to enforce developer explicitness.\n            revert InvalidSalt({emitter: _SELF});\n        } else if (senderBytes == SenderBytes.ZeroAddress && redeployProtectionFlag == RedeployProtectionFlag.True) {\n            // Configures solely a cross-chain redeploy protection. In order to prevent a pseudo-randomly\n            // generated cross-chain redeploy protection, we enforce the zero address check for the first 20 bytes.\n            guardedSalt = _efficientHash({a: bytes32(block.chainid), b: salt});\n        } else if (\n            senderBytes == SenderBytes.ZeroAddress && redeployProtectionFlag == RedeployProtectionFlag.Unspecified\n        ) {\n            // Reverts if the 21st byte is greater than `0x01` in order to enforce developer explicitness.\n            revert InvalidSalt({emitter: _SELF});\n        } else {\n            // For the non-pseudo-random cases, the salt value `salt` is hashed to prevent the safeguard mechanisms\n            // from being bypassed. Otherwise, the salt value `salt` is not modified.\n            guardedSalt = (salt != _generateSalt()) ? keccak256(abi.encode(salt)) : salt;\n        }\n    }\n\n    /**\n     * @dev Returns the enum for the selection of a permissioned deploy protection as well as a\n     * cross-chain redeploy protection.\n     * @param salt The 32-byte random value used to create the contract address.\n     * @return senderBytes The 8-byte enum for the selection of a permissioned deploy protection.\n     * @return redeployProtectionFlag The 8-byte enum for the selection of a cross-chain redeploy\n     * protection.\n     */\n    function _parseSalt(\n        bytes32 salt\n    ) internal view returns (SenderBytes senderBytes, RedeployProtectionFlag redeployProtectionFlag) {\n        if (address(bytes20(salt)) == msg.sender && bytes1(salt[20]) == hex\"01\") {\n            (senderBytes, redeployProtectionFlag) = (SenderBytes.MsgSender, RedeployProtectionFlag.True);\n        } else if (address(bytes20(salt)) == msg.sender && bytes1(salt[20]) == hex\"00\") {\n            (senderBytes, redeployProtectionFlag) = (SenderBytes.MsgSender, RedeployProtectionFlag.False);\n        } else if (address(bytes20(salt)) == msg.sender) {\n            (senderBytes, redeployProtectionFlag) = (SenderBytes.MsgSender, RedeployProtectionFlag.Unspecified);\n        } else if (address(bytes20(salt)) == address(0) && bytes1(salt[20]) == hex\"01\") {\n            (senderBytes, redeployProtectionFlag) = (SenderBytes.ZeroAddress, RedeployProtectionFlag.True);\n        } else if (address(bytes20(salt)) == address(0) && bytes1(salt[20]) == hex\"00\") {\n            (senderBytes, redeployProtectionFlag) = (SenderBytes.ZeroAddress, RedeployProtectionFlag.False);\n        } else if (address(bytes20(salt)) == address(0)) {\n            (senderBytes, redeployProtectionFlag) = (SenderBytes.ZeroAddress, RedeployProtectionFlag.Unspecified);\n        } else if (bytes1(salt[20]) == hex\"01\") {\n            (senderBytes, redeployProtectionFlag) = (SenderBytes.Random, RedeployProtectionFlag.True);\n        } else if (bytes1(salt[20]) == hex\"00\") {\n            (senderBytes, redeployProtectionFlag) = (SenderBytes.Random, RedeployProtectionFlag.False);\n        } else {\n            (senderBytes, redeployProtectionFlag) = (SenderBytes.Random, RedeployProtectionFlag.Unspecified);\n        }\n    }\n\n    /**\n     * @dev Returns the `keccak256` hash of `a` and `b` after concatenation.\n     * @param a The first 32-byte value to be concatenated and hashed.\n     * @param b The second 32-byte value to be concatenated and hashed.\n     * @return hash The 32-byte `keccak256` hash of `a` and `b`.\n     */\n    function _efficientHash(bytes32 a, bytes32 b) internal pure returns (bytes32 hash) {\n        assembly (\"memory-safe\") {\n            mstore(0x00, a)\n            mstore(0x20, b)\n            hash := keccak256(0x00, 0x40)\n        }\n    }\n\n    /**\n     * @dev Generates pseudo-randomly a salt value using a diverse selection of block and\n     * transaction properties.\n     * @return salt The 32-byte pseudo-random salt value.\n     */\n    function _generateSalt() internal view returns (bytes32 salt) {\n        unchecked {\n            salt = keccak256(\n                abi.encode(\n                    // We don't use `block.number - 256` (the maximum value on the EVM) to accommodate\n                    // any chains that may try to reduce the amount of available historical block hashes.\n                    // We also don't subtract 1 to mitigate any risks arising from consecutive block\n                    // producers on a PoS chain. Therefore, we use `block.number - 32` as a reasonable\n                    // compromise, one we expect should work on most chains, which is 1 epoch on Ethereum\n                    // mainnet. Please note that if you use this function between the genesis block and block\n                    // number 31, the block property `blockhash` will return zero, but the returned salt value\n                    // `salt` will still have a non-zero value due to the hashing characteristic and the other\n                    // remaining properties.\n                    blockhash(block.number - 32),\n                    block.coinbase,\n                    block.number,\n                    block.timestamp,\n                    block.prevrandao,\n                    block.chainid,\n                    msg.sender\n                )\n            );\n        }\n    }\n\n    /**\n     * @dev Ensures that `newContract` is a non-zero byte contract.\n     * @param success The Boolean success condition.\n     * @param newContract The 20-byte address where the contract was deployed.\n     */\n    function _requireSuccessfulContractCreation(bool success, address newContract) internal view {\n        // Note that reverting if `newContract == address(0)` isn't strictly necessary here, as if\n        // the deployment fails, `success == false` should already hold. However, since the `CreateX`\n        // contract should be usable and safe on a wide range of chains, this check is cheap enough\n        // that there is no harm in including it (security > gas optimisations). It can potentially\n        // protect against unexpected chain behaviour or a hypothetical compiler bug that doesn't surface\n        // the call success status properly.\n        if (!success || newContract == address(0) || newContract.code.length == 0) {\n            revert FailedContractCreation({emitter: _SELF});\n        }\n    }\n\n    /**\n     * @dev Ensures that `newContract` is a non-zero byte contract.\n     * @param newContract The 20-byte address where the contract was deployed.\n     */\n    function _requireSuccessfulContractCreation(address newContract) internal view {\n        if (newContract == address(0) || newContract.code.length == 0) {\n            revert FailedContractCreation({emitter: _SELF});\n        }\n    }\n\n    /**\n     * @dev Ensures that the contract initialisation call to `implementation` has been successful.\n     * @param success The Boolean success condition.\n     * @param returnData The return data from the contract initialisation call.\n     * @param implementation The 20-byte address where the implementation was deployed.\n     */\n    function _requireSuccessfulContractInitialisation(\n        bool success,\n        bytes memory returnData,\n        address implementation\n    ) internal view {\n        if (!success || implementation.code.length == 0) {\n            revert FailedContractInitialisation({emitter: _SELF, revertData: returnData});\n        }\n    }\n}\n"
    }
  },
  "license": "AGPL-3.0-only",
  "evmVersion": "paris",
  "viaIR": false,
  "metadata": {
    "bytecodeHash": "none"
  },
  "libraries": ""
}

This will revert with:

{
    "success": false,
    "errorCode": 7,
    "errorMsg": "ParserError: Source file requires different compiler version (current compiler is 0.8.19+commit.7dd6d404.Emscripten.clang) - note that nightly builds are considered to be strictly less than the released version\n --> src/CreateX.sol:2:1:\n  |\n2 | pragma solidity 0.8.23;\n  | ^^^^^^^^^^^^^^^^^^^^^^^\n\n"
}

image

PS: I also tried specifying 0.8.23 directly (instead of using latest), but no luck.

🐶 Cute Animal Picture

image

github-actions[bot] commented 9 months ago

Coverage after merging initial-deployments into main will be

100.00%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src
   CreateX.sol100%100%100%100%
pcaversaccio commented 9 months ago

For the record, I detailed the technical verification issues for "Harmony Testnet" and "Filecoin Testnet (Calibration)" in the changelog.

pcaversaccio commented 8 months ago

UPDATE: I managed to verify CreateX on Filfox (i.e. Filecoin) test and production network using the following Python script:

import json
import requests

# See the Filfox API documentation here: https://filfox.notion.site/Filfox-Contract-Verification-API-Documents-c48d361c949348acb0bf806871ddd2c2

address = "0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed"
compiler = "v0.8.23+commit.f704f362"
optimize = True
optimizeRuns = 10000000
metadata = '{"bytecodeHash": "none"}'

sourceFiles = dict()
files = ["CreateX.sol"]

for file in files:
    with open(file) as f:
        sourceFiles[file] = {"content": f.read()}

data = {
    "address": address,
    "compiler": compiler,
    "optimize": optimize,
    "optimizeRuns": optimizeRuns,
    "sourceFiles": sourceFiles,
    "license": "AGPL-3.0-only",
    "evmVersion": "paris",
    "metadata": metadata,
}

url = "https://calibration.filfox.info/api/v1/tools/verifyContract" # For testnet
#  url = "https://filfox.info/api/v1/tools/verifyContract" # For mainnet
header = {"Content-Type": "application/json"}

r = requests.post(url, data=json.dumps(data), headers=header)
print(r.status_code)
print(r.text)