75

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
78

EDIT April 2019: CREATE2 information added.

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(keccak256(0xd6, 0x94, address, 0x80))
nonce1= address(keccak256(0xd6, 0x94, address, 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 ++ senderAddress ++ salt ++ keccak256(init_code))[12:]

More information will be added here and for the meantime see EIP-1014.

  • 4
    For the usecase part, you could mention something about prefunding contracts – Tjaden Hess Jan 30 '16 at 2:11
  • 2
    What 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 5:41
  • 1
    @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 7:04
  • 1
    @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
  • 2
    @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/… :) – eth Jul 17 '17 at 20:08
7

Thanks to eth's answer, it helps 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

enter image description here

  • 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 at 10:52
3

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
2

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
    }
  • 1
    thanks for sharing, wonder where did you get those magic numbers: 0x7f, 0xd6, 0x94 – DiveInto Jul 28 '18 at 13:44
  • 1
  • The nonce can never be 0, so that first test can be removed. – destenson Nov 15 '18 at 9:48
  • Nonce starts with zero, see transactions on etherscan. – Alex Nov 19 '18 at 10:09
1

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")

protected by eth Apr 22 '18 at 9:34

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.