Solidity中的地址可以是帐户或合同(或其他事项,例如交易)。当我有变量x,持有地址时,我该如何测试它是否是合约?
(是的,我已经阅读了文档中的chapter on types)
答案 0 :(得分:47)
是的,您可以使用一些EVM汇编代码来获取地址'代码大小:
function isContract(address addr) returns (bool) {
uint size;
assembly { size := extcodesize(addr) }
return size > 0;
}
答案 1 :(得分:7)
这不是您可以使用Solidity在合同中查询的内容,但如果您只是想知道某个地址是否包含合同代码,您可以使用您的geth控制台或类似代码检查,例如:< / p>
> eth.getCode("0xbfb2e296d9cf3e593e79981235aed29ab9984c0f")
使用十六进制字符串(此处为0xbfb2e296d9cf3e593e79981235aed29ab9984c0f
)作为您要查询的地址。这将返回存储在该地址的字节码。
您还可以使用区块链扫描程序在该地址查找合同的源代码,例如the ecsol library上显示的etherscan.io。
答案 2 :(得分:4)
编辑:自从这个答案第一次写完以来,Solidity已经改变了,@ manuel-aráoz有正确答案。
没有办法确定地址是否是合同。以太坊的目标之一是让人类和智能合同得到平等对待。这导致智能合约与人和其他合同无缝交互的未来。它可能会在未来发生变化,但目前任意地址都不明确。
答案 3 :(得分:1)
发现使用EXTCODESIZE的isContract
功能最受好评的答案是可入侵的。
如果从合同的构造函数中调用此函数,则该函数将返回false(因为尚未部署合同)。
应该非常仔细地使用代码,以免出现安全漏洞,例如:
https://www.reddit.com/r/ethereum/comments/916xni/how_to_pwn_fomo3d_a_beginners_guide(archive)
致repeat:
请勿使用EXTCODESIZE检查来防止智能合约调用函数。这并不是万无一失,它可以通过构造函数调用来破坏,因为在构造函数运行时,该地址的EXTCODESIZE返回0。
请参见sample code,以了解诱使EXTCODESIZE返回0的合同。
如果您要确保EOA正在调用您的合同,则一种简单的方法是require(msg.sender == tx.origin)
。但是,anti-pattern和security的考虑是防止签订合同的原因。
实现帐户抽象后,需要重新访问。
答案 4 :(得分:0)
您可以做什么,授予您手边的信息。 如果交易发件人地址为空或未被占用,则可以判断该地址是合同帐户还是EOA(外部拥有的帐户)。 即,当在网络上发送创建合同事务时,事务中的接收地址为空/未使用。
来自github的参考: https://github.com/ethereum/go-ethereum/wiki/Contracts-and-Transactions
希望这有帮助。
答案 5 :(得分:-1)
简短答案:
require(tx.origin == msg.sender);
tx.origin是发起此串行函数调用的原始地址的引用,而msg.sender是直接调用目标函数的地址。这意味着tx.origin必须是人员,msg.sender可以是合同或人员。因此,如果有人通过合同致电给您,则msg.sender是与tx.origin不同的合同地址。
我知道大多数合同都可以使用@ManuelAráoz的代码,在大多数情况下都可以使用。但是,如果您在合同的构造函数中调用函数,则extcodesize将返回0,这将导致isContract检查失败。
注意:如果您不清楚tx.origin代表什么,则不要在其他情况下使用它。