主页 > 钱包imtoken官网 > 以太坊中如何判断一个地址是合约账户地址

以太坊中如何判断一个地址是合约账户地址

钱包imtoken官网 2023-01-17 06:20:33

0x01 以太坊的两种账户

对以太坊稍有了解的朋友应该知道,以太坊中有两种账户,一种是普通的由私钥控制的外部账户,另一种是与合约代码关联的合约账户。

BTC合约地址是多少_btc提现地址_btc地址

以太坊地址

但是如果我给你下面两个地址,你知道哪个是外部账户地址,哪个是合约账户地址吗?

0x8415A51d68e80aebb916A6f5Dafb8af18bFE2F9d

0x11b314EF962425231150739EF2627FB13214e5Bf

0x02 普通方法

区分的关键是看是否有任何代码与该地址相关联。

EVM 提供了一个操作码 EXTCODESIZE,用于获取与地址关联的代码大小(长度)。 如果是外部账户地址BTC合约地址是多少,则不返回代码。 因此,我们可以通过以下方式来确定合约地址和外部账户地址:

function isContract(address addr) internal view returns (bool) {
    uint256 size;
    assembly { size := extcodesize(addr) }
    return size > 0;
  }

如果是合约外判断,可以使用web3.eth.getCode(),或者对应的JSON-RPC方法eth_getcode。

getCode()用于获取参数地址对应的合约代码。 如果参数是外部账户地址,则返回“0x”; 如果参数是一个合约,它会返回相应的字节码,如下所示:

web3.eth.getCode("0x8415A51d68e80aebb916A6f5Dafb8af18bFE2F9d")
"0x"

web3.eth.getCode("0x11b314EF962425231150739EF2627FB13214e5Bf")
"0x"

什么? 两个地址实际上得到相同的结果! ! ! 如果其中一个地址是合约地址BTC合约地址是多少,我们不应该得到与合约相关的字节码吗? 这两个地址都是外部帐户地址吗?

0x03 未上链合约地址

哈哈,我告诉你,上面两个地址是我链下生成的,代码还没有部署到区块链网络,你当然得不到相关代码。

合约账户地址是如何生成的? 实际上,有两种生成方法。 我使用了一种相对简单的方法来生成它。 生成的公式如下:

合约地址 = keccak256(rlp([sender, nonce]))

对应的java代码为:

 public static String generateAddress(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;
  }

调用代码是:

AddressUtils.generateAddress("0x8415A51d68e80aebb916A6f5Dafb8af18bFE2F9d", 18))

这是什么意思?

当你通过一个地址是否与代码关联来判断一个地址是否为合约账户地址时,你心里一定如明镜一般。 如果地址与代码相关联,则它必须是合约地址。 如果一个地址没有关联代码,则不能确定该地址是外部账户地址也是合约地址。

0x04 怎么办?

一个常见的判断地址类型的需求是只允许外部账户调用我们的合约,不允许合约账户调用我们的合约。 要满足这个要求,只需要在合约中加入这个判断:

require(tx.origin == msg.sender)