如何找出以太坊地址是否合同?

时间:2016-06-05 16:48:33

标签: ethereum solidity smartcontracts

Solidity中的地址可以是帐户或合同(或其他事项,例如交易)。当我有变量x,持有地址时,我该如何测试它是否是合约?

(是的,我已经阅读了文档中的chapter on types

6 个答案:

答案 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_guidearchive

repeat

请勿使用EXTCODESIZE检查来防止智能合约调用函数。这并不是万无一失,它可以通过构造函数调用来破坏,因为在构造函数运行时,该地址的EXTCODESIZE返回0。

请参见sample code,以了解诱使EXTCODESIZE返回0的合同。


如果您要确保EOA正在调用您的合同,则一种简单的方法是require(msg.sender == tx.origin)。但是,anti-patternsecurity的考虑是防止签订合同的原因。

实现帐户抽象后,需要重新访问。

答案 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代表什么,则不要在其他情况下使用它。