solidity - solidity delegatecall 在另一个合约中不起作用
问题描述
我正在尝试一些代码来查找调用和委托调用之间的差异。而且我发现 delegatecall 和 call 都不起作用。
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 VM 中调用 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() 实际上没有被调用?</p>
解决方案
testCall()
工作正常。有一些问题testDelegatecall()
。要了解为什么您首先需要了解其delegatecall
工作原理。这是solidity文档中所说的:
存在一个消息调用的特殊变体,称为委托调用, 它与消息调用相同,除了目标地址处的代码在调用合约的上下文中执行
msg.sender
并且msg.value
不更改它们的值这一事实。
这意味着当您使用.delegatecall()
getaddr()
时将作为Contract B函数的一部分调用。但是_counter
合约 B 中的不退出log
将包含一些垃圾值_counter
。
推荐阅读
- codeigniter - 加载 Excel phpspreadsheet 时如何解决错误 503?
- r - 如何在 R 中创建我自己的二项式系数函数
- python - 仅为日志级别 python 发送电子邮件
- python - Python-验证文件头及其元数据
- ios - 如何遍历包含当前骑手 id 的每个键?
- java - ImageView 动画瞬间恢复到原始位置
- ruby-on-rails - 由于“ActionController::InvalidAuthenticityToken”,Chrome 中的 Post 和 Delete 方法失败
- c# - 读取具有 XML 数据 C# 的文本文件
- php - WordPress:如何每次都将特定用户重定向到特定页面?这与登录后无关
- ubuntu - 如何卸载jprofiler,ubuntu?