How is the address of an Ethereum contract computed? What use cases are there for knowing a contract's address in advance?
7 Answers
EDIT Sept 2023: CREATE2 information clarified.
EDIT January 2022: Updated Solidity syntax to ^0.8.0.
The address for an Ethereum contract is deterministically computed from the address of its creator (sender) and how many transactions the creator has sent (nonce). The sender and nonce are RLP encoded and then hashed with Keccak-256.
From pyethereum:
def mk_contract_address(sender, nonce): return sha3(rlp.encode([normalize_address(sender), nonce]))[12:] In Solidity:
nonce0= address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, bytes1(0x80)))))); nonce1= address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), _origin, bytes1(0x01)))))); Example with some discussion:
For sender 0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0, the contract addresses that it will create are the following:
nonce0= "0xcd234a471b72ba2f1ccf0a70fcaba648a5eecd8d" nonce1= "0x343c43a37d37dff08ae8c4a11544c718abb4fcf8" nonce2= "0xf778b86fa74e846c4f0a1fbd1335fe81c00a0c91" nonce3= "0xfffd933a0bc612844eaf0c6fe3e5b8e9b6c1d19c" In Java with Web3j:
private String calculateContractAddress(String address, long nonce){ byte[] addressAsBytes = Numeric.hexStringToByteArray(address); byte[] calculatedAddressAsBytes = Hash.sha3(RlpEncoder.encode( new RlpList( RlpString.create(addressAsBytes), RlpString.create((nonce))))); calculatedAddressAsBytes = Arrays.copyOfRange(calculatedAddressAsBytes, 12, calculatedAddressAsBytes.length); String calculatedAddressAsHex = Numeric.toHexString(calculatedAddressAsBytes); return calculatedAddressAsHex; } Note: As per EIP 161 A Specification contract accounts are initiated with nonce = 1 (in the mainnet). So the first contract address, created by another contract, will be computed with non-zero nonce.
CREATE2
A new opcode, CREATE2 was added in EIP-1014 that is another way that a contract can be created.
For contract created by CREATE2 its address will be:
keccak256( 0xff ++ address(this) ++ salt ++ keccak256(init_code))[12:]
More information will be added here and for the meantime see EIP-1014.
- 6For the usecase part, you could mention something about prefunding contractsTjaden Hess– Tjaden Hess2016-01-30 02:11:57 +00:00Commented Jan 30, 2016 at 2:11
- 4What if the creator is a contract itself? Has the address also a nonce? Is it increased by every call it makes or only with the creation of new contacts? Or is the address and nonce of tx.origin relevant?mKoeppelmann– mKoeppelmann2016-01-30 05:41:12 +00:00Commented Jan 30, 2016 at 5:41
- 3@mKoeppelmann: Same computation if creator is a contract; nonce increases every single transaction an account makes (new contract/account would start at nonce 0), and the address and nonce of earlier senders (such as tx.origin) do not affect address of new contract.2016-01-30 07:04:22 +00:00Commented Jan 30, 2016 at 7:04
- 2@eth: "nonce increases every single transaction" this is what confuses me, because in the definition in the yellowpaper only human controlled accounts can make transactions. A transaction is something that is signed with a private key. Contracts can only make calls that are triggered by transactions. So I wonder what "calls" increase the nonce of a contract. All calls or only calls that create a new contract?mKoeppelmann– mKoeppelmann2016-01-30 19:21:39 +00:00Commented Jan 30, 2016 at 19:21
- 3@StevenRoose Yes, contracts have nonces. A nonce of a contract is only incremented when that contract creates another contract. It's in separate question Martin asked ethereum.stackexchange.com/questions/764/… :)2017-07-17 20:08:14 +00:00Commented Jul 17, 2017 at 20:08
Thanks to eth's answer, it helped a lot to resolve $2000 issue.
Just solved issue with funds, which were sent in main Ethereum network to address of smart contract, deployed to test Ethereum network. We used same wallet to deploy different smart contract in main Ethereum network several times until transaction field nonce achieved the same value 13, as were used to deploy on test network. We called special method of freshly deployed smart contract to reclaim funds. So smart contract was deployed after it was really funded: https://etherscan.io/address/0x9c86825280b1d6c7dB043D4CC86E1549990149f9
Just finished an article about this issue: https://medium.com/@k06a/how-we-sent-eth-to-the-wrong-address-and-successfully-recovered-them-2fc18e09d8f6
- Thanks.. but what if the mainnet contract owner has current nonce higher than the one was used to create contract in testnet. I have same situation as your.. but only probelm is that my main net owner wallet has latest nonce 236 and testnet contract was created at 13 nonce.. is there any way to override and deploy contract having previous nonce?Yogesh - EtherAuthority.io– Yogesh - EtherAuthority.io2019-03-15 10:52:24 +00:00Commented Mar 15, 2019 at 10:52
- 1At current gas fees, you would pay a fortune to deploy the contract 12 times, before you got to 13. Why did you not set the nonce to 13 right away?Qwerty– Qwerty2021-12-20 18:16:52 +00:00Commented Dec 20, 2021 at 18:16
- @Qwerty you can set a nonce yourself for deployment?Sky– Sky2022-02-01 09:51:22 +00:00Commented Feb 1, 2022 at 9:51
- @Sky Yes, in metamask when confirming the transaction. I just tried it with REMIX. If you don't see it in Metamask, enable advanced options.Qwerty– Qwerty2022-02-02 16:03:14 +00:00Commented Feb 2, 2022 at 16:03
- This is old, but for future reference: @Yogesh-EtherAuthority.io As you might know, it is not possible to arbitrarily set the nonce or revert to a previous nonce in Ethereum. The nonce increases sequentially and cannot be skipped or reverted. Also, a contract deployed with a previous nonce cannot be modified. However, if the existing contract was designed using the "proxy pattern," you could rewrite and redeploy the "logic contract" and then use the proxy contract to call the functions of this new logic contract.starriet 차주녕– starriet 차주녕2024-12-24 15:42:26 +00:00Commented Dec 24, 2024 at 15:42
Here's a node.js script that deterministically computes an Ethereum contract address given the contract creator's public address and nonce value.
Let me know if anyone has questions about inputs, etc.
// node version: v9.10.0 // module versions: // [email protected] // [email protected] const rlp = require("rlp"); const keccak = require("keccak"); var nonce = 0x00; //The nonce must be a hex literal! var sender = "0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0"; //Requires a hex string as input! var input_arr = [sender, nonce]; var rlp_encoded = rlp.encode(input_arr); var contract_address_long = keccak("keccak256") .update(rlp_encoded) .digest("hex"); var contract_address = contract_address_long.substring(24); //Trim the first 24 characters. console.log("contract_address: " + contract_address); Note that the nonce can be incremented normally, just remember that it's a hex value.
Output (nonce = 0x00):
contract_address: cd234a471b72ba2f1ccf0a70fcaba648a5eecd8d Output (nonce = 0x01):
contract_address: 343c43a37d37dff08ae8c4a11544c718abb4fcf8 -
- 1Here is a good explanation: ethereum.stackexchange.com/questions/19092/…kawthuldrok– kawthuldrok2018-06-10 01:30:36 +00:00Commented Jun 10, 2018 at 1:30
Here is updated Python version for modern Ethereum libraries (eth-utils):
import rlp from eth_utils import keccak, to_checksum_address, to_bytes def mk_contract_address(sender: str, nonce: int) -> str: """Create a contract address using eth-utils. # https://ethereum.stackexchange.com/a/761/620 """ sender_bytes = to_bytes(hexstr=sender) raw = rlp.encode([sender_bytes, nonce]) h = keccak(raw) address_bytes = h[12:] return to_checksum_address(address_bytes) print(to_checksum_address(mk_contract_address(to_checksum_address("0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0"), 1))) print("0x343c43a37d37dff08ae8c4a11544c718abb4fcf8") assert mk_contract_address(to_checksum_address("0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0"), 1) == \ to_checksum_address("0x343c43a37d37dff08ae8c4a11544c718abb4fcf8") RLP done in solidity (did not test this though, beware! just for understanding):
function addressFrom(address _origin, uint _nonce) public pure returns (address) { if(_nonce == 0x00) return address(keccak256(byte(0xd6), byte(0x94), _origin, byte(0x80))); if(_nonce <= 0x7f) return address(keccak256(byte(0xd6), byte(0x94), _origin, byte(_nonce))); if(_nonce <= 0xff) return address(keccak256(byte(0xd7), byte(0x94), _origin, byte(0x81), uint8(_nonce))); if(_nonce <= 0xffff) return address(keccak256(byte(0xd8), byte(0x94), _origin, byte(0x82), uint16(_nonce))); if(_nonce <= 0xffffff) return address(keccak256(byte(0xd9), byte(0x94), _origin, byte(0x83), uint24(_nonce))); return address(keccak256(byte(0xda), byte(0x94), _origin, byte(0x84), uint32(_nonce))); // more than 2^32 nonces not realistic } - 1thanks for sharing, wonder where did you get those magic numbers: 0x7f, 0xd6, 0x94DiveInto– DiveInto2018-07-28 13:44:44 +00:00Commented Jul 28, 2018 at 13:44
- 1github.com/ethereum/wiki/wiki/RLP#definitionAlex– Alex2018-08-21 20:42:24 +00:00Commented Aug 21, 2018 at 20:42
- The nonce can never be 0, so that first test can be removed.Dennis Estenson– Dennis Estenson2018-11-15 09:48:21 +00:00Commented Nov 15, 2018 at 9:48
- Nonce starts with zero, see transactions on etherscan.Alex– Alex2018-11-19 10:09:09 +00:00Commented Nov 19, 2018 at 10:09
Here is a pure ethers.js implementation in TypeScript, returning a checksummed address. nonce is expected to be a regular number.
(ethers.js does have a function called getContractAddress too, but it cannot be used for any nonce)
import { ethers } from 'hardhat'; static getContractAddress(address: string, nonce: number): string { const rlp_encoded = ethers.utils.RLP.encode( [address, ethers.BigNumber.from(nonce.toString()).toHexString()] ); const contract_address_long = ethers.utils.keccak256(rlp_encoded); const contract_address = '0x'.concat(contract_address_long.substring(26)); return ethers.utils.getAddress(contract_address); } - This implementation works in case the nonce is greater than 0. For nonce = 0 the result is not correct (see example and compare with result of the top answer). A simple one-liner that works correctly in ethers.js is
const contractAddress = ethers.utils.getContractAddress({from, nonce});GongFu– GongFu2022-01-04 21:48:50 +00:00Commented Jan 4, 2022 at 21:48 - @GongFu yes, better to use the in-built function. At the time I believe I was using an outdated version of Ethers that did not have this function.riordant– riordant2022-01-07 02:10:10 +00:00Commented Jan 7, 2022 at 2:10
The contract address is typically a hash of the sender's address and sender's wallet nonce. The actual contract code doesn't make any difference - the hash is the same regardless of the code.
Above I said typically because there are other ways of deploying contracts. If an existing contract deploys a contract with a special opcode CREATE2 the contract address is calculated a bit differently.
You can check details for example here: https://medium.com/coinmonks/smart-contract-address-creation-method-difference-between-smart-contract-address-and-wallet-97b421506455
- Upvoted but merging with earlier question to gather answers together.2022-10-14 01:33:54 +00:00Commented Oct 14, 2022 at 1:33
- I already started wondering did I accidentally answer a question with valid previous answers already.Lauri Peltonen– Lauri Peltonen2022-10-14 06:53:57 +00:00Commented Oct 14, 2022 at 6:53
- No problem! Sometimes helpful to merge, sometimes not. Thanks for all your work. (I've upvoted many, but many others do not seem to vote much.)2022-10-15 05:38:17 +00:00Commented Oct 15, 2022 at 5:38
