Skip to content

Commit

Permalink
Make SSTORE2 deployments use CREATE3
Browse files Browse the repository at this point in the history
  • Loading branch information
Vectorized committed Jul 13, 2024
1 parent 55f2b77 commit aeafd33
Show file tree
Hide file tree
Showing 6 changed files with 744 additions and 712 deletions.
1,127 changes: 564 additions & 563 deletions .gas-snapshot

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ utils
├─ LibPRNG — "Library for generating pseudorandom numbers"
├─ Base64 — "Library for Base64 encoding and decoding"
├─ SSTORE2 — "Library for cheaper reads and writes to persistent storage"
├─ CREATE3 — "Deploy to deterministic addresses without an initcode factor"
├─ CREATE3 — "Deterministic deployments agnostic to the initialization code"
├─ LibRLP — "Library for RLP encoding and CREATE address computation"
├─ LibBit — "Library for bit twiddling and boolean operations"
├─ LibZip — "Library for compressing and decompressing bytes"
Expand Down
83 changes: 22 additions & 61 deletions src/utils/CREATE3.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Deploy to deterministic addresses without an initcode factor.
/// @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)
Expand All @@ -13,9 +13,6 @@ library CREATE3 {
/// @dev Unable to deploy the contract.
error DeploymentFailed();

/// @dev Unable to initialize the contract.
error InitializationFailed();

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* BYTECODE CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
Expand Down Expand Up @@ -44,12 +41,12 @@ library CREATE3 {
* -------------------------------------------------------------------+
*/

/// @dev The proxy bytecode.
uint256 private constant _PROXY_BYTECODE = 0x67363d3d37363d34f03d5260086018f3;
/// @dev The proxy initialization code.
uint256 private constant _PROXY_INITCODE = 0x67363d3d37363d34f03d5260086018f3;

/// @dev Hash of the `_PROXY_BYTECODE`.
/// @dev Hash of the `_PROXY_INITCODE`.
/// Equivalent to `keccak256(abi.encodePacked(hex"67363d3d37363d34f03d5260086018f3"))`.
bytes32 private constant _PROXY_BYTECODE_HASH =
bytes32 internal constant PROXY_INITCODE_HASH =
0x21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f;

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
Expand All @@ -76,52 +73,25 @@ library CREATE3 {
{
/// @solidity memory-safe-assembly
assembly {
// Store the `_PROXY_BYTECODE` into scratch space.
mstore(0x00, _PROXY_BYTECODE)
// Deploy a new contract with our pre-made bytecode via CREATE2.
mstore(0x00, _PROXY_INITCODE) // Store the `_PROXY_INITCODE`.
let proxy := create2(0, 0x10, 0x10, salt)

// If the result of `create2` is the zero address, revert.
if iszero(proxy) {
// Store the function selector of `DeploymentFailed()`.
mstore(0x00, 0x30116425)
// Revert with (offset, size).
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}

// Store the proxy's address.
mstore(0x14, proxy)
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)
// Nonce of the proxy contract (1).
mstore8(0x34, 0x01)

mstore8(0x34, 0x01) // Nonce of the proxy contract (1).
deployed := keccak256(0x1e, 0x17)

// If the `call` fails, revert.
if iszero(
call(
gas(), // Gas remaining.
proxy, // Proxy's address.
value, // Ether value.
add(initCode, 0x20), // Start of `initCode`.
mload(initCode), // Length of `initCode`.
0x00, // Offset of output.
0x00 // Length of output.
mul( // The arguments of `mul` are evaluated last to first.
extcodesize(deployed),
call(gas(), proxy, value, add(initCode, 0x20), mload(initCode), 0x00, 0x00)
)
) {
// Store the function selector of `InitializationFailed()`.
mstore(0x00, 0x19b991a8)
// Revert with (offset, size).
revert(0x1c, 0x04)
}

// If the code size of `deployed` is zero, revert.
if iszero(extcodesize(deployed)) {
// Store the function selector of `InitializationFailed()`.
mstore(0x00, 0x19b991a8)
// Revert with (offset, size).
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
Expand All @@ -140,27 +110,18 @@ library CREATE3 {
{
/// @solidity memory-safe-assembly
assembly {
// Cache the free memory pointer.
let m := mload(0x40)
// Store `deployer`.
mstore(0x00, deployer)
// Store the prefix.
mstore8(0x0b, 0xff)
// Store the salt.
mstore(0x20, salt)
// Store the bytecode hash.
mstore(0x40, _PROXY_BYTECODE_HASH)

// Store the proxy's address.
mstore(0x14, keccak256(0x0b, 0x55))
// Restore the free memory pointer.
mstore(0x40, m)
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)
// Nonce of the proxy contract (1).
mstore8(0x34, 0x01)

mstore8(0x34, 0x01) // Nonce of the proxy contract (1).
deployed := keccak256(0x1e, 0x17)
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/utils/ERC1967FactoryConstants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ library ERC1967FactoryConstants {
bytes internal constant BYTECODE =
hex"6080604052600436106100b15760003560e01c8063545e7c611161006957806399a88ec41161004e57806399a88ec41461019d578063a97b90d5146101b0578063db4c545e146101c357600080fd5b8063545e7c61146101775780639623609d1461018a57600080fd5b80633729f9221161009a5780633729f922146101315780634314f120146101445780635414dff01461015757600080fd5b80631acfd02a146100b65780632abbef15146100d8575b600080fd5b3480156100c257600080fd5b506100d66100d1366004610604565b6101e6565b005b3480156100e457600080fd5b506101076100f3366004610637565b30600c908152600091909152602090205490565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61010761013f366004610652565b610237565b6101076101523660046106d7565b61024e565b34801561016357600080fd5b50610107610172366004610738565b610267565b610107610185366004610604565b61029a565b6100d66101983660046106d7565b6102af565b6100d66101ab366004610604565b61035f565b6101076101be366004610751565b610370565b3480156101cf57600080fd5b506101d86103a9565b604051908152602001610128565b30600c52816000526020600c2033815414610209576382b429006000526004601cfd5b81905580827f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f600080a35050565b60006102468484843685610370565b949350505050565b600061025e8585838087876103c2565b95945050505050565b6000806102726103a9565b905060ff600053806035523060601b6001528260155260556000209150600060355250919050565b60006102a88383368461024e565b9392505050565b30600c5283600052336020600c2054146102d1576382b429006000526004601cfd5b6040518381527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc602082015281836040830137600080836040018334895af1610331573d610327576355299b496000526004601cfd5b3d6000803e3d6000fd5b5082847f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c7600080a350505050565b61036c82823660006102af565b5050565b60008360601c33148460601c151761039057632f6348366000526004601cfd5b61039f868686600187876103c2565b9695505050505050565b6000806103b461049c565b608960139091012092915050565b6000806103cd61049c565b90508480156103e757866089601384016000f592506103f3565b6089601383016000f092505b50816104075763301164256000526004601cfd5b8781527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc602082015282846040830137600080846040018334865af161045a573d6103275763301164256000526004601cfd5b30600c5281600052866020600c20558688837fc95935a66d15e0da5e412aca0ad27ae891d20b2fb91cf3994b6a3bf2b8178082600080a4509695505050505050565b6040513060701c801561054257666052573d6000fd607b8301527f3d356020355560408036111560525736038060403d373d3d355af43d6000803e60748301527f3735a920a3ca505d382bbc545af43d6000803e6052573d6000fd5b3d6000f35b60548301527f14605757363d3d37363d7f360894a13ba1a3210667c828492db98dca3e2076cc60348301523060148301526c607f3d8160093d39f33d3d337382525090565b66604c573d6000fd60758301527f3d3560203555604080361115604c5736038060403d373d3d355af43d6000803e606e8301527f3735a920a3ca505d382bbc545af43d6000803e604c573d6000fd5b3d6000f35b604e8301527f14605157363d3d37363d7f360894a13ba1a3210667c828492db98dca3e2076cc602e83015230600e8301526c60793d8160093d39f33d3d336d82525090565b803573ffffffffffffffffffffffffffffffffffffffff811681146105ff57600080fd5b919050565b6000806040838503121561061757600080fd5b610620836105db565b915061062e602084016105db565b90509250929050565b60006020828403121561064957600080fd5b6102a8826105db565b60008060006060848603121561066757600080fd5b610670846105db565b925061067e602085016105db565b9150604084013590509250925092565b60008083601f8401126106a057600080fd5b50813567ffffffffffffffff8111156106b857600080fd5b6020830191508360208285010111156106d057600080fd5b9250929050565b600080600080606085870312156106ed57600080fd5b6106f6856105db565b9350610704602086016105db565b9250604085013567ffffffffffffffff81111561072057600080fd5b61072c8782880161068e565b95989497509550505050565b60006020828403121561074a57600080fd5b5035919050565b60008060008060006080868803121561076957600080fd5b610772866105db565b9450610780602087016105db565b935060408601359250606086013567ffffffffffffffff8111156107a357600080fd5b6107af8882890161068e565b96999598509396509294939250505056fea26469706673582212200ac7c3ccbc2d311c48bf5465b021542e0e306fe3c462c060ba6a3d2f81ff6c5f64736f6c63430008130033";

/// @dev The initcode used to deploy the canonical ERC1967Factory.
/// @dev The initialization code used to deploy the canonical ERC1967Factory.
bytes internal constant INITCODE = abi.encodePacked(
hex"608060405234801561001057600080fd5b506107f6806100206000396000f3fe", BYTECODE
);
Expand Down
Loading

0 comments on commit aeafd33

Please sign in to comment.