微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

检查 msg.sender 是否是特定类型的合约

如何解决检查 msg.sender 是否是特定类型的合约

就像现在一样,任何人都可以在 setMyString调用 FirstContract 函数。我试图将对该函数的访问限制为 SecondContract 的实例。但不是一个特定的实例,任何 SecondContract 类型的合约都应该能够调用 setMyString

contract FirstContract{
    String public myString;

    function setMyString(String memory what) public {
        myString=what;
    }
}

contract SecondContract{
    address owner;
    address firstAddress;
    FirstContract firstContract;
    constructor(address _1st){
        owner=msg.sender;
        firstAddress=_1st;
        firstContract=FirstContract(firstAddress);
    }
    function callFirst(String memory what){
        require(msg.sender==owner);
        firstContract.setMyString("hello");
    }
}

解决方法

Solidity 目前没有一种简单的方法来根据接口验证地址。

您可以检查字节码,它是否包含指定的签名(公共属性和方法)。这需要比通常的 StackOverflow 答案更大的范围,因此我将只描述步骤而不是编写代码。

首先,定义您要查找的所需签名列表(名称和参数数据类型的 keccak256 散列的前 4 个字节)。您可以在我的其他答案 herehere 中找到有关签名的更多信息。

documentation 中的一个示例展示了如何将任何地址的(在您的情况下为 msg.sender)字节码作为 bytes(动态长度数组)。

然后您需要遍历返回的 bytes 数组并搜索 4 字节签名。

如果您发现它们全部,则意味着 msg.sender “实现了接口”。如果外部合同中缺少任何签名,则表示它没有实现接口。


但是...我真的建议您重新考虑列入白名单的方法。是的,您需要维护列表并在 new setIsSecondContract() 第一次调用 SecondContract 函数时调用 setMyString()。但是对于 FirstContractsetMyString() 函数的所有调用者来说,它的 Gas 效率更高,而且首先更容易编写和测试功能。

contract FirstContract{
    String public myString;
    
    address owner;
    mapping (address => bool) isSecondContract;
    
    modifier onlySecondContract {
        require(isSecondContract[msg.sender]);
        _;
    }
    
    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }
    
    function setIsSecondContract(address _address,bool _value) public onlyOwner {
        isSecondContract[_address] = _value;
    }

    function setMyString(String memory what) public onlySecondContract {
        myString=what;
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。