Ethereum 将用户地址与数组中定义的地址匹配的方式

Ethereum 将用户地址与数组中定义的地址匹配的方式,ethereum,solidity,smartcontracts,Ethereum,Solidity,Smartcontracts,我正在寻找一种有效的方法,通过将msg.sender与我在部署时硬编码的地址数组进行比较,检查调用函数的人是否被允许访问智能合约中定义的函数。我可以用for loop来做,但这需要很多汽油。提前谢谢。起初我想告诉你们这是没办法的,但后来我有了一个有趣的想法,结果很好但是请注意,只有在编译时知道地址的情况下,这才有效。 注意:在我的实验中,我对任务做了一些修改-我将把msg.sender与黑名单地址进行比较。将其更改为您的用例很简单 直观解 实现您建议的功能的直观方法可能如下所示: pragma

我正在寻找一种有效的方法,通过将msg.sender与我在部署时硬编码的地址数组进行比较,检查调用函数的人是否被允许访问智能合约中定义的函数。我可以用for loop来做,但这需要很多汽油。提前谢谢。

起初我想告诉你们这是没办法的,但后来我有了一个有趣的想法,结果很好但是请注意,只有在编译时知道地址的情况下,这才有效。

注意:在我的实验中,我对任务做了一些修改-我将把msg.sender与黑名单地址进行比较。将其更改为您的用例很简单

直观解 实现您建议的功能的直观方法可能如下所示:

pragma solidity ^0.4.18;

contract DataInStorage {

    uint counter;

    address[] public blackListed = [ 0x281055afc982d96fab65b3a49cac8b878184cb16, 0x6f46cf5569aefa1acc1009290c8e043747172d89 ]
    function increment() public {
        for (uint i=0; i<blackListed.length; i++) {
            require(msg.sender != blackListed[i]);
        }
        counter += 1;
    }

}
<number of addresses>   |  <gas spent>
100                     |  124808
200                     |  207708
我用更多的地址尝试了这种模式,这里有一个有趣的结果

<number of addresses>   |  <gas spent>
100                     |  45338
200                     |  49038
|
100                     |  45338
200                     |  49038
因此,在这种情况下,一个地址验证只需花费我们37美元。这比使用合同存储的解决方案好22倍左右。

如果有人能提供更多的技术解释,为什么在EVM中加载代码比加载数据存储便宜得多,我会很乐意听到

完整示例 代码中的数据(100个地址)

代码中的数据(200个地址)

存储器中的数据(100个地址)

存储器中的数据(200个地址)


用块菌测试

使用映射来存储此数据

mapping(address => bool) public blacklisted;

也可以将其用作修改器:

  modifier notBlacklisted() {
    require(!blacklisted[msg.sender]);
    _;                                                                                                                                                                                                                                         
}
然后在函数中:

function foo() notBlacklisted public
{
  // do stuff
}

只有未被列入黑名单的用户才能使用该功能。

非常感谢您的解释:)。这真的很有帮助。我不推荐这种方法。这不仅是在代码中看到的噩梦,而且还使列表不可变。另外,对于gas比较,您是对的,与迭代数组相比,它更便宜,但是您忽略了部署时gas的差异。更好的解决方案是使用部署时填充的
映射
,可通过事务更新,并签入修饰符(
require(myMap[msg.sender])
,其中
myMap
是一个
映射(address->bool)
)@AdamKipnis您完全正确。请将您的解决方案作为答案发布,我将删除我的,以保持整洁。
  modifier notBlacklisted() {
    require(!blacklisted[msg.sender]);
    _;                                                                                                                                                                                                                                         
}
function foo() notBlacklisted public
{
  // do stuff
}