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