Article Summary
GPT 4

原理

以太坊有两种类型的账户:普通账户和合约账户。合约是通过发送带有空字段的事务(空的 to)来创建的,并且包含一些被执行的数据(一个构造函数),并且希望返回一些放在区块链上的代码。 这些合同自然是与正常账户相同的地址空间的一部分; 由此确定合同的地址:

address = sha3(rlp_encode(creator_account, creator_account_nonce))[12:]

合约地址是确定性的,由 keccack256(address,nonce) 计算。(其中 address 是合约的地址(或创建交易的以太坊地址),而 nonce 是合约生产其它合约的一个数值(或者对于常规交易来说是交易的nonce))。

从本质上讲,合约的地址就是账户与交易 nonce 串联的 keccak256 哈希值。合约的 nonce 是以 1 开始的,账户的交易 nonce 是以 0 开始的。

contract KeylessHiddenEthCreator {
    uint public currentcontractNonce = 1; // keep track of this contract's nonce publicly (it's also found in the contract's state

    // determine future addresses which can hide ether.
    function futureAddresses(uint8 nonce) public view returns (address) {
        if (nonce == 0) {
            return address(keccak256(0xd6, 0x94, this, 0x80));
        } else {
            return address(keccak256(0xd6, 0x94, this, nonce));
        }
        // need to implement rlp encoding properly for a full range of nonces
        // increment the contract nonce or retrieve ether from a hidden/key-less account provided the nonce is correct
    }

    function retrieveHiddenEther(address beneficiary) public returns (address) {
        currentContractNonce += 1;
        return new RecoverContract(beneficiary);
    }

    function payable {} // Allow ether transfers (helps for playing in remix)
}

contract RecoverContract {
    constructor(address beneficiary) {
        selfdestruct(beneficiary); 

地址计算脚本

python

import rlp
from ethereum import utils
address = 0xD8d6E16b2a224bB1Cd7e600c0b37603e341b4d93
nonce = 1
rlp_res = rlp.encode([address,nonce])
print(rlp_res)
sha3_res = utils.mk_contract_address(address,nonce)
print(sha3_res)
sha3_res_de = utils.decode_addr(sha3_res)
print("contract_address: " + sha3_res_de)

solidity

pragma solidity ^0.8.0;

contract Hack {
    function getdd(address target) public view returns (address) {
        address data = address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), target, bytes1(0x01))))));
        return data;
    }
}