Как рассчитывается адрес контракта Ethereum?

Как вычисляется адрес контракта Ethereum? Какие существуют случаи, когда вы заранее знаете адрес контракта?

54 голоса | спросил eth 30 Jam1000000amSat, 30 Jan 2016 01:14:56 +030016 2016, 01:14:56

4 ответа


60

Адрес для контракта Ethereum детерминистически вычисляется по адресу его создателя (sender) и сколько транзакций отправил создатель (nonce). sender и nonce кодируются RLP, а затем хешируются с помощью Keccak-256 .

От 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))

Пример с некоторым обсуждением:

Для отправителя 0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0, адреса контракта, которые он будет создавать, следующие:

nonce0= "0xcd234a471b72ba2f1ccf0a70fcaba648a5eecd8d"
nonce1= "0x343c43a37d37dff08ae8c4a11544c718abb4fcf8"
nonce2= "0xf778b86fa74e846c4f0a1fbd1335fe81c00a0c91"
nonce3= "0xfffd933a0bc612844eaf0c6fe3e5b8e9b6c1d19c"

В Java с 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;
}

Примечание : согласно EIP 161 A Спецификация Контракт начинается с nonce = 1 (в сети). Таким образом, первый контрактный адрес, созданный другим контрактом, будет вычисляться с ненулевым nonce.

ответил eth 30 Jam1000000amSat, 30 Jan 2016 01:14:56 +030016 2016, 01:14:56
4

Благодаря ответу eth , он помогает решить проблему 2000 долл. США.

Просто решена проблема с фондами, которые были отправлены в сеть main Ethereum для адреса смарт-контракта, развернутого в сети test Ethereum. Мы использовали тот же кошелек для развертывания разного смарт-контракта в сети main Ethereum несколько раз, пока поле транзакции nonce не достигло того же значения 13, которое использовалось для развертывания в тесте . Мы вызвали специальный метод недавно развернутого смарт-контракта для возврата средств. Такой умный контракт был развернут после того, как он был действительно финансирован: https://etherscan.io/address/0x9c86825280b1d6c7dB043D4CC86E1549990149f9

Только что закончил статью об этой проблеме: https://medium.com/@k06a/how-we-sent-eth-to-the-wrong-address-and-successfully-recovered-them-2fc18e09d8f6

 введите описание изображения здесь>> </a> </p></body></html>

ответил k06a 1 32017vEurope/Moscow11bEurope/MoscowWed, 01 Nov 2017 17:51:45 +0300 2017, 17:51:45
3

Вот сценарий node.js, который детерминистически вычисляет адрес контракта Ethereum с учетом общедоступного адреса создателя контракта и значения nonce.

Сообщите мне, есть ли у кого-нибудь вопросы о входах и т. д.

//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);

Обратите внимание, что nonce может быть увеличено нормально, просто помните, что это шестнадцатеричное значение.

Выход (nonce = 0x00):

contract_address: cd234a471b72ba2f1ccf0a70fcaba648a5eecd8d

Выход (nonce = 0x01):

contract_address: 343c43a37d37dff08ae8c4a11544c718abb4fcf8
ответил kawthuldrok 28 AMpSat, 28 Apr 2018 04:33:21 +030033Saturday 2018, 04:33:21
0

RLP сделано в прочности (не проверяйте это, но будьте осторожны! просто для понимания):

    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
    }
ответил Alex 30 AMpMon, 30 Apr 2018 09:00:28 +030000Monday 2018, 09:00:28

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132