]> git.ardis.lu - minimal-create2/commitdiff
Initial commit
authorArdis Lu <ardisglu@gmail.com>
Sat, 17 Jun 2023 06:59:18 +0000 (23:59 -0700)
committerArdis Lu <ardisglu@gmail.com>
Sat, 17 Jun 2023 06:59:18 +0000 (23:59 -0700)
README.md [new file with mode: 0644]
create2-deployment.evm [new file with mode: 0644]
create2.evm [new file with mode: 0644]
minimal-contract-deployment.evm [new file with mode: 0644]

diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..38c049d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,88 @@
+# minimal-create2
+
+This is the minimal amount of code required to mine a smart contract address using `CREATE2`.
+
+## Create the `CREATE2` deployment factory
+
+Create a new smart contract with the minimum amount of code required to call `CREATE2` by pasting this code into DevTools (assuming Metamask is installed):
+
+```javascript
+await ethereum.request({
+  method: 'eth_sendTransaction',
+  params: [{
+    from: (await ethereum.request({ method: 'eth_requestAccounts' }))[0], // Your currently active MetaMask address
+    data: '0x6d365f5f375f516020360360205ff55f52600e6012f3' // create2-deployment.evm, compiled
+  }]
+});
+```
+
+`create2-deployment.evm` contains bytecode that deploys `create2.evm`. `create2.evm` is a minimal smart contract written in EVM assembly which expects a 32-byte salt and arbitrary bytecode in its calldata and deploys the bytecode using the `CREATE2` opcode.
+
+**Important**: If you want the same `CREATE2` contract address *across chains*, you should use a fresh EOA with no prior transactions to create this deployment factory. Otherwise, the deployment factories will have different addresses and will output different `CREATE2` addresses.
+
+## Mine the desired `CREATE2` address
+
+Simple example of predicting the `CREATE2` address:
+
+```javascript
+const ethers = await import('https://cdn.jsdelivr.net/npm/ethers@6.6.0/+esm');
+
+// The smart contract you deployed in "Create the CREATE2 deployment factory"
+const factory = '0x8137a81A74E2a9d510898B2e3E307e7C33eBad8A';
+
+// Salt must be hex and exactly 32 bytes
+const salt = '0x0000000000000000000000000000000000000000000000000000000000000123';
+
+// Must be the entire creation bytecode, including constructor arguments
+const bytecode = '0x385f818153f3'; // minimal-contract-deployment.evm, compiled
+
+ethers.getCreate2Address(factory, salt, ethers.keccak256(bytecode));
+// 0xD7ada5e4De61a3c14994046d349d90F7ae693433
+```
+
+Example of mining a specific smart contract address by testing different `salt` values:
+
+```javascript
+const ethers = await import('https://cdn.jsdelivr.net/npm/ethers@6.6.0/+esm');
+
+// The smart contract you deployed in "Create the CREATE2 deployment factory"
+const factory = '0x8137a81A74E2a9d510898B2e3E307e7C33eBad8A';
+
+// Must be the entire creation bytecode, including constructor arguments
+const bytecode = '0x385f818153f3'; // minimal-contract-deployment.evm, compiled
+
+const requirement = /^0xbeef/;
+
+let salt = 1;
+while (true) {
+  const paddedSalt = `0x${salt.toString(16).padStart(64, '0')}`;
+  const addr = ethers.getCreate2Address(factory, paddedSalt, ethers.keccak256(bytecode));
+  if (requirement.test(addr)) {
+    console.log({factory, paddedSalt, bytecode, addr});
+    break;
+  }
+  salt++;
+}
+// {factory: '0x8137a81A74E2a9d510898B2e3E307e7C33eBad8A', paddedSalt: '0x000000000000000000000000000000000000000000000000000000000005c342', bytecode: '0x385f818153f3', addr: '0xbeef7906063D950306868AF5af36955015110f84'}
+```
+
+## Using the mined `salt`
+
+Once a desired `CREATE2` address has been mined, you can deploy it by sending the mined `salt` parameter to the smart contract deployed in "Create the `CREATE2` deployment factory".
+
+```javascript
+// Same parameters from "Mine the desired CREATE2 address"
+const factory = '8137a81A74E2a9d510898B2e3E307e7C33eBad8A'; // Drop "0x" prefix
+const salt = '000000000000000000000000000000000000000000000000000000000005c342'; // Drop "0x" prefix
+const bytecode = '385f818153f3'; // Drop "0x" prefix
+
+await ethereum.request({
+  method: 'eth_sendTransaction',
+  params: [{
+    from: (await ethereum.request({ method: 'eth_requestAccounts' }))[0], // Your currently active MetaMask address
+    to: `0x${factory}`,
+    data: `0x${salt}${bytecode}`
+  }]
+});
+// Smart contract is deployed as 0xbeef7906063D950306868AF5af36955015110f84, as predicted
+```
diff --git a/create2-deployment.evm b/create2-deployment.evm
new file mode 100644 (file)
index 0000000..7f76902
--- /dev/null
@@ -0,0 +1,12 @@
+;; Store create2.evm compiled bytecode into memory
+PUSH 0x365f5f375f516020360360205ff5 
+PUSH0
+MSTORE
+
+;; Return create2.evm compiled bytecode
+PUSH 14
+PUSH 18
+RETURN
+
+;; This contract, compiled:
+;; 6d365f5f375f516020360360205ff55f52600e6012f3
diff --git a/create2.evm b/create2.evm
new file mode 100644 (file)
index 0000000..a768e8e
--- /dev/null
@@ -0,0 +1,23 @@
+;; Copy calldata to memory offset 0
+CALLDATASIZE
+PUSH0
+PUSH0
+CALLDATACOPY
+
+
+;; First 32 bytes of calldata is the salt
+PUSH0
+MLOAD
+
+;; Remaining calldata is the creation bytecode
+PUSH 32
+CALLDATASIZE
+SUB
+
+;; Call CREATE2
+PUSH 32
+PUSH0
+CREATE2
+
+;; This contract, compiled:
+;; 365f5f375f516020360360205ff5
diff --git a/minimal-contract-deployment.evm b/minimal-contract-deployment.evm
new file mode 100644 (file)
index 0000000..f01dc05
--- /dev/null
@@ -0,0 +1,13 @@
+;; This is the minimal bytecode that can be used to deploy a new smart contract
+CODESIZE
+PUSH0
+DUP2
+DUP2
+MSTORE8
+RETURN
+
+;; This smart contract, compiled:
+;; 385f818153f3
+
+;; When sent to EVM, this smart contract will deploy a new smart contract with bytecode:
+;; 060000000000
This page took 0.047991 seconds and 4 git commands to generate.