我正在尝试一些代码来查找调用和委托调用之间的区别。 我发现没有其他委托调用,也没有调用。
pragma solidity ^0.4.23;
contract A{
address public owner; // storage
uint256 counter = 0;
event addrLog(address _addr, uint256 _counter);
function getaddr() public returns(address addr){
addr = address(this);
owner = addr;
emit addrLog(owner, ++counter);
}
}
contract B{
address public owner; // storage, will used A.owner if A is existed.
// see a strange usage, I tried bug got compile err, not understanded.
// address public testAddr = address of A;
address public testAddr;
bytes4 public messageId;
bool public r1;
bool public r2;
constructor(address _addressOfCalltest) public {
testAddr = _addressOfCalltest;
}
function testCall() public returns(bool){
messageId = bytes4(keccak256("getaddr()"));
return testAddr.call(messageId);
}
function testDelegatecall() public returns(bool){
messageId = bytes4(keccak256("getaddr()"));
return testAddr.delegatecall(messageId);
}
function run() public{
r1 = testCall();
r2 = testDelegatecall();
}
}
当我在JS虚拟机中调用A.getaddr()时,日志确定,可以正常工作。
[
{
"from": "0xef55bfac4228981e850936aaf042951f7b146e41",
"topic": "0xff2a5ce99c57a44e471dfcb9313f2cc369b2abf37959acedfbeb720f304545e6",
"event": "addrLog",
"args": {
"0": "0xef55BfAc4228981E850936AAf042951F7b146e41",
"1": "2",
"_addr": "0xef55BfAc4228981E850936AAf042951F7b146e41",
"_counter": "2",
"length": 2
}
}
]
但是,当我调用B.run()或B.testCall()或B.testDelegatecall()时,它不起作用,日志为空:
[]
和r1,r2都从false更改为true,这意味着testAddr.call(messageId)和testAddr.delegatecall(messageId)均成功运行。所以我的问题是为什么log为null,这意味着没有实际调用getaddr()?
答案 0 :(得分:0)
testCall()
工作正常。 testDelegatecall()
有一些问题。要了解为什么首先需要了解delegatecall
的工作原理。这是solidity documentation中所说的话:
存在一个特殊的消息呼叫变体,名为 delegatecall 除了代码的事实,这与消息调用相同 在目标地址中在调用上下文中执行 合同以及
msg.sender
和msg.value
不会更改其值。
使用.delegatecall()
getaddr()
意味着合同B 功能的一部分。但是由于_counter
不在合同B中退出,log
将包含_counter
的一些垃圾值。
答案 1 :(得分:0)
@lftifar Taz,谢谢。
问题1:正如您所说,我对合同B进行了如下修改,
contract B{
address public owner;
address public testAddr;
bytes4 public messageId;
bool public r1;
bool public r2;
uint256 counter = 0;
...
}
再次编译并运行testCall,日志仍然是[]。
Q2:函数getaddr()返回合同的地址; 预期在调用testCall时,合同A的返回地址,预期A.owner是A的地址,但它是0x00;否则,它是0x00。 期望当调用testDelegatecall时,返回合同B(不是A)的地址,期望B.owner是B的地址,但是它是0x00;
这就是为什么我怀疑getaddr根本没有被testCall或testDelegatecall调用的原因, 这就是为什么我为getaddr添加了日志打印的原因。但是现在我更加困惑了。