// Source: contracts/deploy/Create2.sol pragma solidity ^0.8.0; // SPDX-License-Identifier: MIT // File contracts/interfaces/IDeploy.sol /** * @title IDeploy Interface * @notice This interface defines the errors for a contract that is responsible for deploying new contracts. */ interface IDeploy { error EmptyBytecode(); error AlreadyDeployed(); error DeployFailed(); } // File contracts/libs/ContractAddress.sol library ContractAddress { function isContract(address contractAddress) internal view returns (bool) { bytes32 existingCodeHash = contractAddress.codehash; // https://eips.ethereum.org/EIPS/eip-1052 // keccak256('') == 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 return existingCodeHash != bytes32(0) && existingCodeHash != 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; } } // File contracts/deploy/Create2.sol /** * @title Create2 contract * @notice This contract can be used to deploy a contract with a deterministic address that depends on * the contract bytecode, deployer address, and deployment salt. */ contract Create2 is IDeploy { using ContractAddress for address; /** * @notice Deploys a new contract using the `CREATE2` method. * @dev This function deploys the contract using `CREATE2` opcode. * @param bytecode The bytecode of the contract to be deployed * @param deploySalt A salt to influence the contract address * @return deployed The address of the deployed contract */ function _create2(bytes memory bytecode, bytes32 deploySalt) internal returns (address deployed) { deployed = _create2Address(bytecode, deploySalt); if (bytecode.length == 0) revert EmptyBytecode(); if (deployed.isContract()) revert AlreadyDeployed(); assembly { deployed := create2(0, add(bytecode, 32), mload(bytecode), deploySalt) } if (deployed == address(0)) revert DeployFailed(); } /** * @notice Computes the deployed address that will result from the `CREATE2` method. * @param bytecode The bytecode of the contract to be deployed * @param deploySalt A salt to influence the contract address * @return address The deterministic contract address if it was deployed */ function _create2Address(bytes memory bytecode, bytes32 deploySalt) internal view returns (address) { return address( uint160( uint256( keccak256( abi.encodePacked( hex'ff', address(this), deploySalt, keccak256(bytecode) // init code hash ) ) ) ) ); } }