检查 msg.sender 是否是特定类型的合同
Check if msg.sender is a specific type of contract
就像现在一样,任何人都可以调用 FirstContract
中的 setMyString
函数。我正在尝试将对该函数的访问限制为 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 目前没有一种简单的方法来根据接口验证地址。
您可以检查字节码,它是否包含指定的签名(public 属性和方法)。这需要比通常的 Whosebug 答案更大的范围,所以我只是描述步骤而不是编写代码。
首先,定义您要查找的所需签名列表(名称和参数数据类型的 keccak256 散列的前 4 个字节)。您可以在我的其他答案中找到有关签名的更多信息 here and 。
documentation 中的示例显示了如何将任何地址(在您的情况下为 msg.sender
)字节码作为 bytes
(动态长度数组)。
然后您需要遍历返回的 bytes
数组并搜索 4 字节签名。
如果找到它们 all,则意味着 msg.sender
“实现了接口”。如果外部合约中缺少任何个签名,则意味着它没有实现接口。
但是...我真的建议您重新考虑您的白名单方法。是的,当 new SecondContract
第一次想要调用 setMyString()
函数时,您需要维护列表并调用 setIsSecondContract()
。但对于 FirstContract
的 setMyString()
函数的所有调用者来说,它的 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;
}
}
就像现在一样,任何人都可以调用 FirstContract
中的 setMyString
函数。我正在尝试将对该函数的访问限制为 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 目前没有一种简单的方法来根据接口验证地址。
您可以检查字节码,它是否包含指定的签名(public 属性和方法)。这需要比通常的 Whosebug 答案更大的范围,所以我只是描述步骤而不是编写代码。
首先,定义您要查找的所需签名列表(名称和参数数据类型的 keccak256 散列的前 4 个字节)。您可以在我的其他答案中找到有关签名的更多信息 here and
documentation 中的示例显示了如何将任何地址(在您的情况下为 msg.sender
)字节码作为 bytes
(动态长度数组)。
然后您需要遍历返回的 bytes
数组并搜索 4 字节签名。
如果找到它们 all,则意味着 msg.sender
“实现了接口”。如果外部合约中缺少任何个签名,则意味着它没有实现接口。
但是...我真的建议您重新考虑您的白名单方法。是的,当 new SecondContract
第一次想要调用 setMyString()
函数时,您需要维护列表并调用 setIsSecondContract()
。但对于 FirstContract
的 setMyString()
函数的所有调用者来说,它的 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;
}
}