// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Deterministic deployments agnostic to the initialization code. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/CREATE3.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/CREATE3.sol) /// @author Modified from 0xSequence (https://github.com/0xSequence/create3/blob/master/contracts/Create3.sol) library CREATE3 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Unable to deploy the contract. error DeploymentFailed(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BYTECODE CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * -------------------------------------------------------------------+ * Opcode | Mnemonic | Stack | Memory | * -------------------------------------------------------------------| * 36 | CALLDATASIZE | cds | | * 3d | RETURNDATASIZE | 0 cds | | * 3d | RETURNDATASIZE | 0 0 cds | | * 37 | CALLDATACOPY | | [0..cds): calldata | * 36 | CALLDATASIZE | cds | [0..cds): calldata | * 3d | RETURNDATASIZE | 0 cds | [0..cds): calldata | * 34 | CALLVALUE | value 0 cds | [0..cds): calldata | * f0 | CREATE | newContract | [0..cds): calldata | * -------------------------------------------------------------------| * Opcode | Mnemonic | Stack | Memory | * -------------------------------------------------------------------| * 67 bytecode | PUSH8 bytecode | bytecode | | * 3d | RETURNDATASIZE | 0 bytecode | | * 52 | MSTORE | | [0..8): bytecode | * 60 0x08 | PUSH1 0x08 | 0x08 | [0..8): bytecode | * 60 0x18 | PUSH1 0x18 | 0x18 0x08 | [0..8): bytecode | * f3 | RETURN | | [0..8): bytecode | * -------------------------------------------------------------------+ */ /// @dev The proxy initialization code. uint256 private constant _PROXY_INITCODE = 0x67363d3d37363d34f03d5260086018f3; /// @dev Hash of the `_PROXY_INITCODE`. /// Equivalent to `keccak256(abi.encodePacked(hex"67363d3d37363d34f03d5260086018f3"))`. bytes32 internal constant PROXY_INITCODE_HASH = 0x21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CREATE3 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Deploys `initCode` deterministically with a `salt`. /// Returns the deterministic address of the deployed contract, /// which solely depends on `salt`. function deployDeterministic(bytes memory initCode, bytes32 salt) internal returns (address deployed) { deployed = deployDeterministic(0, initCode, salt); } /// @dev Deploys `initCode` deterministically with a `salt`. /// The deployed contract is funded with `value` (in wei) ETH. /// Returns the deterministic address of the deployed contract, /// which solely depends on `salt`. function deployDeterministic(uint256 value, bytes memory initCode, bytes32 salt) internal returns (address deployed) { /// @solidity memory-safe-assembly assembly { mstore(0x00, _PROXY_INITCODE) // Store the `_PROXY_INITCODE`. let proxy := create2(0, 0x10, 0x10, salt) if iszero(proxy) { mstore(0x00, 0x30116425) // `DeploymentFailed()`. revert(0x1c, 0x04) } mstore(0x14, proxy) // Store the proxy's address. // 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01). // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex). mstore(0x00, 0xd694) mstore8(0x34, 0x01) // Nonce of the proxy contract (1). deployed := keccak256(0x1e, 0x17) if iszero( mul( // The arguments of `mul` are evaluated last to first. extcodesize(deployed), call(gas(), proxy, value, add(initCode, 0x20), mload(initCode), 0x00, 0x00) ) ) { mstore(0x00, 0x30116425) // `DeploymentFailed()`. revert(0x1c, 0x04) } } } /// @dev Returns the deterministic address for `salt`. function predictDeterministicAddress(bytes32 salt) internal view returns (address deployed) { deployed = predictDeterministicAddress(salt, address(this)); } /// @dev Returns the deterministic address for `salt` with `deployer`. function predictDeterministicAddress(bytes32 salt, address deployer) internal pure returns (address deployed) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, deployer) // Store `deployer`. mstore8(0x0b, 0xff) // Store the prefix. mstore(0x20, salt) // Store the salt. mstore(0x40, PROXY_INITCODE_HASH) // Store the bytecode hash. mstore(0x14, keccak256(0x0b, 0x55)) // Store the proxy's address. mstore(0x40, m) // Restore the free memory pointer. // 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01). // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex). mstore(0x00, 0xd694) mstore8(0x34, 0x01) // Nonce of the proxy contract (1). deployed := keccak256(0x1e, 0x17) } } }