Как рассчитывается адрес контракта Ethereum?
Как вычисляется адрес контракта Ethereum? Какие существуют случаи, когда вы заранее знаете адрес контракта?
4 ответа
Адрес для контракта 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 , он помогает решить проблему 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
Вот сценарий 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
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
}