To see the contract that uses CREATE2, jump to Step 2. The new opcode was added to the Ethereum virtual machine nearly a year ago — at the end of February 2019. This opcode introduced a second method of calculating the address of a new smart contract (previously only was available). Using is certainly more complex than the original . You can no longer just write in Solidity, and instead must resort to writing in assembly code. CREATE2 CREATE CREATE2 CREATE new Token() However has an important property that makes it preferable in certain situations: it doesn’t rely on the current state of the deploying address. This means you can be sure the contract address calculated today would be the same as the address calculated 1 year from now. This is important is because you can interact with the address, and send it ETH, before the smart contract has been deployed to it. CREATE2 So, with few practical walk-throughs available online, I decided to create this simple explanatory blog to explain: How and each work CREATE CREATE2 How to use in your smart contract, and CREATE2 How I used it to solve one of the challenges Capture The Ether The CREATE opcode. This is the opcode used by default to deploy contracts. The resulting contract address is calculated by hashing: The deploying address The number of contracts that have previously been deployed from that address — known as the nonce keccak256(rlp.encode(deployingAddress, nonce))[ :] 12 The CREATE2 opcode. This opcode was introduced to Ethereum in February 2019 and so is still relatively new. It is essentially just another way to deploy a smart contract, but with a different way to calculate the new contract address. It uses: The deploying address The hash of the bytecode being deployed A random ‘salt’ (32 byte string), supplied by the creator. keccak256( ++ deployingAddr ++ salt ++ keccak256(bytecode))[ :] 0xff 12 The Challenge For my worked example using , I'm going to solve the . To complete the task defined on the challenge page, you need to create a contract that has 2 properties: CREATE2 Fuzzy Identity challenge on Capture the Ether Has a function that returns name() bytes32("smarx") Has the string somewhere in its address. badc0de The first is easy to implement. The second is where the challenge comes in, and to complete it we must use knowledge of how Ethereum calculates contract addresses — which we just went over! Solve it with CREATE? To succeed in this challenge using the opcode we’d need to generate many private keys. For each of these we would calculate the corresponding Ethereum address, use a nonce of to calculate the resulting contract address. CREATE 0 Solve it with CREATE2? Using just 1 Ethereum address, we instead can just loop through different salt values until we find one that works. This seems like a nice option over generating potentially hundreds of thousands of private keys. Considering Capture the Ether was created in 2018, was certainly not the intended solution for the problem — but I think it sounds like the nicer option. CREATE2 The Solution To use to find an address containing we need: CREATE2 badc0de The bytecode of the contract to be deployed The address deploying the contract (a contract that uses ) CREATE2 Our salt — that we will calculate. Step 1: The bytecode of contract to be deployed The first step is to get the bytecode of the contract that we want to deploy at an address containing badc0de. The contract to pass is simple, and can be defined as follows: the challenge pragma solidity ^ ; contract BadCodeSmarx is IName { { FuzzyIdentityChallenge(_challenge).authenticate(); } { bytes32( ); } } 0.5 .12 ( ) function callAuthenticate address _challenge public ( ) ( ) function name external view returns bytes32 return "smarx" Running a quick , the bytecode can then be found inside : truffle compile /build/BadCodeSmarx.json : "bytecode" "0x608060405234801561001057600080fd5b506101468061002..." Or the same result can be achieved using instead of Truffle. Remix Step 2: A contract that uses CREATE2 Now we can define a simple contract that is provided a salt, and uses to deploy this bytecode: CREATE2 contract Deployer { bytes contractBytecode = hex ; { bytes memory bytecode = contractBytecode; address addr; assembly { := create2( , add(bytecode, ), mload(bytecode), salt) } } } "608060405234801561001057600080fd5b5061015d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806306fdde031461003b5780637872ab4914610059575b600080fd5b61004361009d565b6040518082815260200191505060405180910390f35b61009b6004803603602081101561006f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506100c5565b005b60007f736d617278000000000000000000000000000000000000000000000000000000905090565b8073ffffffffffffffffffffffffffffffffffffffff1663380c7a676040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561010d57600080fd5b505af1158015610121573d6000803e3d6000fd5b505050505056fea265627a7a72315820fb2fc7a07f0eebf799c680bb1526641d2d905c19393adf340a04e48c9b527de964736f6c634300050c0032" ( ) function deploy bytes32 salt public addr 0 0x20 In Solidity assembly, create2() takes 4 parameters: 1: The amount of wei to send to the new contract as . This is 0 for this example. msg.value 2–3: The location of the bytecode in memory 4: The salt — that we will calculate in step 3. We leave this as a parameter so it can we provided after we have calculated it. It also returns the address of the created contract — which you must catch in a variable whether or not you want to use it. So now this contract is ready to go. I deployed it on Ropsten testnet at: . Now that we know the address that will be deploying our contract, and we have the bytecode, all we need to do is calculate a salt that will result in address containing . 0xca4dfd86a86c48c5d9c228bedbeb7f218a29c94b BadCodeSmarx badc0de Step 3: Calculating the salt To find a salt that will result in an address containing , we need a simple script to loop through each salt one by one, and calculate the address it would obtain. badc0de So as to ensure the script was calculating the resulting address correctly, I deployed a contract using salt . I then used that contract address to ensure my script was correctly formatting and hashing parameters — and therefore producing the same address as does onchain. 0x00...001 CREATE2 As a reminder — the formula for address creation is as follows, where means the first 12 bytes are removed to find the address. [12:] keccak256( ++ deployingAddr ++ salt ++ keccak256(bytecode))[ :] 0xff 12 Here is the script I used. I used the package ethereumjs-util to perform keccak256 hashes — you can find it on . Github eth = ( ) string1 = string2 = ( i = ; i < ; i++) { saltToBytes = i.toString( ).padStart( , ) concatString = string1.concat(saltToBytes).concat(string2) hashed = eth.bufferToHex(eth.keccak256(concatString)) (hashed.substr( ).includes( )) { .log(saltToBytes) } } const require 'ethereumjs-util' // 0xff ++ deployingAddress is fixed: var '0xffca4dfd86a86c48c5d9c228bedbeb7f218a29c94b' // Hash of the bytecode is fixed. Calculated with eth.keccak256(): var '4670da3f633e838c2746ca61c370ba3dbd257b86b28b78449f4185480e2aba51' // In each loop, i is the value of the salt we are checking for var 0 72057594037927936 // 1. Convert i to hex, and it pad to 32 bytes: var 16 64 '0' // 2. Concatenate this between the other 2 strings var // 3. Hash the resulting string var // 4. Remove leading 0x and 12 bytes // 5. Check if the result contains badc0de if 26 'badc0de' console break Running this script, less than 30 seconds later out popped my resulting salt: 0x00000000000000000000000000000000000000000000000000000000005b2bfe Then all I had to do was execute . Lo and behold an instance of was deployed at: Deployer.deploy(0x00...005b2bfe) BadCodeSmarx 0xa905a3922a4ebfbc7d257cecdb1df04a3 badc0de References: EIP1014 — Skinny CREATE2 Capture the Ether — Fuzzy Identity Truffle ethereumjs-util