团结委托电话不适用于其他合同

时间:2019-02-18 14:12:56

标签: solidity

我正在尝试一些代码来查找调用和委托调用之间的区别。 我发现没有其他委托调用,也没有调用。

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()?

2 个答案:

答案 0 :(得分:0)

testCall()工作正常。 testDelegatecall()有一些问题。要了解为什么首先需要了解delegatecall的工作原理。这是solidity documentation中所说的话:

  

存在一个特殊的消息呼叫变体,名为 delegatecall   除了代码的事实,这与消息调用相同   在目标地址中在调用上下文中执行   合同以及msg.sendermsg.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添加了日志打印的原因。但是现在我更加困惑了。