内容简介:本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
0x01 以太坊中的两类账户
对以太坊稍微了解一些朋友,应该知道,以太坊中有两类账户,一类是普通的由私钥控制的外部账户,一类是关联有合约代码的合约账户。 ![以太坊地址]( https://upload ...
0x01 以太坊中的两类账户
对以太坊稍微了解一些朋友,应该知道,以太坊中有两类账户,一类是普通的由私钥控制的外部账户,一类是关联有合约代码的合约账户。
但是如果我给你下面两个地址,你知道哪个是外部账户地址,哪个是合约账户地址么? 0x8415A51d68e80aebb916A6f5Dafb8af18bFE2F9d 0x11b314EF962425231150739EF2627FB13214e5Bf
0x02 常用方法
区分的关键是看这个地址有没有与之相关联的代码。 EVM 提供了一个操作码 EXTCODESIZE,用来获取地址相关联的代码大小(长度),如果是外部账号地址,则没有代码返回。因此我们可以使用以下方法判断合约地址及外部账号地址:
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"
什么?两个地址竟然得到同样的结果!!!如果其中一个地址是合约地址的话,不是应该得到合约关联的字节码么?难道两个地址都是外部账户地址?
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)
0x01 以太坊中的两类账户
对以太坊稍微了解一些朋友,应该知道,以太坊中有两类账户,一类是普通的由私钥控制的外部账户,一类是关联有合约代码的合约账户。
但是如果我给你下面两个地址,你知道哪个是外部账户地址,哪个是合约账户地址么? 0x8415A51d68e80aebb916A6f5Dafb8af18bFE2F9d 0x11b314EF962425231150739EF2627FB13214e5Bf
0x02 常用方法
区分的关键是看这个地址有没有与之相关联的代码。 EVM 提供了一个操作码 EXTCODESIZE,用来获取地址相关联的代码大小(长度),如果是外部账号地址,则没有代码返回。因此我们可以使用以下方法判断合约地址及外部账号地址:
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"
什么?两个地址竟然得到同样的结果!!!如果其中一个地址是合约地址的话,不是应该得到合约关联的字节码么?难道两个地址都是外部账户地址?
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)
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
- 发表于 6分钟前
- 阅读 ( 5 )
- 学分 ( 0 )
- 分类:以太坊
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 智能合约安全:短地址攻击
- [技术交流] solidity 汇编实现合约地址的计算器
- 通过CREATE2获得合约地址:解决交易所充值账号
- 干货 | Solidity 安全:已知攻击方法和常见防御模式综合列表,Part-4:外部合约引用、短地址攻击
- 智能合约攻击分析之庞氏代币合约漏洞
- 检测了3万多份智能合约,这份白皮书找到了9大智能合约安全漏洞(附下载链接)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java Web高级编程
威廉斯 (Nicholas S.Williams) / 王肖锋 / 清华大学出版社 / 2015-6-1 / CNY 99.80
Java成为世界上编程语言之一是有其优势的。熟悉JavaSE的程序员可以轻松地进入到Java EE开发中,构建出安全、可靠和具有扩展性的企业级应用程序。编写《Java Web高级编程——涵盖WebSockets、Spring Framework、JPA Hibernate和 Spring Security》一书的目的正是如此。 《Java Web高级编程:涵盖WebSockets、Sp......一起来看看 《Java Web高级编程》 这本书的介绍吧!