前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【知识】以太坊中如何判断一个地址为合约账户地址

【知识】以太坊中如何判断一个地址为合约账户地址

作者头像
辉哥
发布2021-05-18 11:19:05
6.2K2
发布2021-05-18 11:19:05
举报
文章被收录于专栏:区块链入门区块链入门

0x01 以太坊中的两类账户

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

image

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

0x02 常用方法

区分的关键是看这个地址有没有与之相关联的代码。 EVM 提供了一个操作码 EXTCODESIZE,用来获取地址相关联的代码大小(长度),如果是外部账号地址,则没有代码返回。因此我们可以使用以下方法判断合约地址及外部账号地址:

代码语言:javascript
复制
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";如果参数是合约,则返回对应的字节码,如下所示:

代码语言:javascript
复制
web3.eth.getCode("0x8415A51d68e80aebb916A6f5Dafb8af18bFE2F9d")
"0x"
代码语言:javascript
复制
web3.eth.getCode("0x11b314EF962425231150739EF2627FB13214e5Bf")
"0x"

什么?两个地址竟然得到同样的结果!!!如果其中一个地址是合约地址的话,不是应该得到合约关联的字节码么?难道两个地址都是外部账户地址?

0x03 未上链的合约地址

哈哈,告诉你吧,上面两个地址中的其中一个地址,是我在链下生成的,代码还没部署到区块链网络中呢,你当然得不到关联代码啦。 合约账户地址是怎么生成的呢?其实有两种生成方式,我是用的比较简单的方式生成的,生成的公式如下:

代码语言:javascript
复制
合约地址 = keccak256(rlp([sender, nonce]))

对应的 java 代码为:

代码语言:javascript
复制
 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;
  }

调用代码为:

代码语言:javascript
复制
AddressUtils.generateAddress("0x8415A51d68e80aebb916A6f5Dafb8af18bFE2F9d", 18))

这说明什么? 当你通过是否关联有代码来判断一个地址是否是合约账户地址时,心里要明镜似的,一个地址关联有代码,那它肯定是合约地址,如果一个地址没有代码关联,并不能肯定这个地址是外部账户地址还是合约地址。

0x04 怎么办?

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

代码语言:javascript
复制
require(tx.origin == msg.sender)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x01 以太坊中的两类账户
  • 0x02 常用方法
  • 0x03 未上链的合约地址
  • 0x04 怎么办?
相关产品与服务
访问管理
访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档