How is the address of an Ethereum contract computed? What use cases are there for knowing a contract's address in advance?
-
In addition to @eth answer it should be noted that you take last 20 bytes. – Timofey Solonin Apr 17 '18 at 17:54
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.
- 85,679
- 53
- 285
- 406
-
6For the usecase part, you could mention something about prefunding contracts – Tjaden Hess Jan 30 '16 at 02: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 Jan 30 '16 at 05: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. – eth Jan 30 '16 at 07: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 Jan 30 '16 at 19:21
-
1I think the question I am asking is getting a little bit of topic so I created a new question here: http://ethereum.stackexchange.com/questions/764/do-contracts-also-have-a-nonce – mKoeppelmann Jan 30 '16 at 19:29
-
What happens in the case of a contract creating a contract? Does a contract also have a sequence number? – Steven Roose Jul 17 '17 at 09:47
-
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 https://ethereum.stackexchange.com/questions/764/do-contracts-also-have-a-nonce :) – eth Jul 17 '17 at 20:08
-
2
-
-
Here is online smart contract address calculator with full CREATE2 support: https://toolkit.abdk.consulting/ethereum#contract-address – Mikhail Vladimirov Jan 21 '20 at 20:22
-
@MikhailVladimirov Thanks, if you have time to post a separate answer, explaining the different fields / how to use your calculator, I will update my CREATE2 answer to point to yours. – eth Jan 25 '20 at 12:52
-
1For Solidity ^0.6.0, I had to use
address(uint160(uint256(keccak256(abi.encodePacked(byte(0xd6), byte(0x94), _origin, byte(0x80))))))(for nonce0). – erwaman Apr 24 '20 at 14:32 -
For calculating address of a contract deployed using
CREATE2you need to replacesenderAddresswithaddress(this), i.e. the address of the factory contract (that calls theCREATE2opcode) itself. See https://docs.soliditylang.org/en/v0.8.21/yul.html#opcodes in which it says "current contract’s address". – SKYBITDEV3 Sep 12 '23 at 21:18 -
i.e. many people may wrongly think
senderAddressismsg.sender, but it really should beaddress(this). e.g. see Solidity code at https://github.com/axelarnetwork/axelar-gmp-sdk-solidity/blob/d859f6f62ff04c5c40d4508ed72caabf4394f0db/contracts/deploy/Create2.sol#L48-L64 – SKYBITDEV3 Sep 12 '23 at 21:54 -
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
- 3,016
- 2
- 21
- 35
-
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 Mar 15 '19 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 Dec 20 '21 at 18:16
-
-
@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 Feb 02 '22 at 16:03
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:
// rlp@2.0.0
// keccak@1.4.0
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
- 231
- 1
- 9
- 241
- 2
- 6
-
-
1Here is a good explanation: https://ethereum.stackexchange.com/questions/19092/why-was-rlp-chosen-as-the-low-level-protocol-encoding-algorithm – kawthuldrok Jun 10 '18 at 01: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")
- 791
- 5
- 20
- 22,269
- 6
- 62
- 127
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
}
- 283
- 3
- 6
-
1thanks for sharing, wonder where did you get those magic numbers: 0x7f, 0xd6, 0x94 – DiveInto Jul 28 '18 at 13:44
-
1
-
-
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
- 29,391
- 3
- 20
- 57
-
-
I already started wondering did I accidentally answer a question with valid previous answers already. – Lauri Peltonen Oct 14 '22 at 06: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.) – eth Oct 15 '22 at 05:38
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);
}
- 89
- 10
-
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 Jan 04 '22 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 Jan 07 '22 at 02:10
