简体   繁体   English

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

[英]Check if msg.sender is a specific type of contract

As it is now, anyone can call the setMyString function in the FirstContract .现在,任何人都可以在FirstContract中调用setMyString function 。 I'm trying to restrict access to that function to an instance of SecondContract .我正在尝试将对 function 的访问限制为SecondContract的实例。 But not one specific instance, any contract of type SecondContract should be able to call setMyString .但不是一个特定的实例,任何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 currently doesn't have an easy way to validate an address against an interface. Solidity 目前还没有一种简单的方法可以根据接口验证地址。

You can check the bytecode, whether it contains the specified signatures (of the public properties and methods).您可以检查字节码,它是否包含(公共属性和方法的)指定签名。 This requires a bit larger scope than a usual StackOverflow answer, so I'm just going to describe the steps instead of writing the code.这需要比通常的 StackOverflow 答案大一点的 scope,所以我只描述步骤而不是编写代码。

First, define the desired list of signatures (1st 4 bytes of keccak256 hash of the name and arguments datatypes) that you're going to be looking for.首先,定义您要查找的签名列表(名称的 keccak256 hash 和 arguments 数据类型的第一个 4 个字节)。 You can find more info about signatures in my other answers here and here .您可以在此处此处的我的其他答案中找到有关签名的更多信息。

An example in the documentation shows how to get any address's (in your case msg.sender ) bytecode as bytes (dynamic-length array). 文档中的一个示例显示了如何将任何地址(在您的情况下为msg.sender )字节码作为bytes (动态长度数组)获取。

You'll then need to loop through the returned bytes array and search for the 4-byte signatures.然后,您需要遍历返回的bytes数组并搜索 4 字节签名。

If you find them all , it means that msg.sender "implements the interface".如果全部找到,则意味着msg.sender “实现了接口”。 If any of the signatures is missing in the external contract, it means it doesn't implement the interface.如果外部合约中缺少任何签名,则意味着它没有实现接口。


But... I'd really recommend you to rethink your approach to whitelisting.但是......我真的建议你重新考虑你的白名单方法。 Yes, you'll need to maintain the list and call setIsSecondContract() when a new SecondContract wants to call the setMyString() function for the first time.是的,当SecondContract想要第一次调用setMyString() function 时,您需要维护列表并调用setIsSecondContract() But it's more gas efficient for all callers of the FirstContract 's setMyString() function, as well as easier to write and test the functionality in the first place.但是对于FirstContractsetMyString() function 的所有调用者来说,它的 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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM