图文并茂详细介绍Solidity的三种合约间的调用方式 call、delegatecall 和 callcode

最近开始学习以太坊智能合约编程,其中涉及到智能合约之间的函数调用。
Solidity的三种合约间的调用方式有call、delegatecall 和 callcode这3种方式。参考了下面的文章:
https://www.cnblogs.com/x-poior/p/10511552.html

对于文章中提到的三种调用方式的异同点
call: 最常用的调用方式,调用后内置变量 msg 的值会修改为调用者,执行环境为被调用者的运行环境(合约的 storage)。
delegatecall: 调用后内置变量 msg 的值不会修改为调用者,但执行环境为调用者的运行环境。
callcode: 调用后内置变量 msg 的值会修改为调用者,但执行环境为调用者的运行环境。

初步感觉不好理解,于是按文中给出的智能合约例子直接运行一次。我使用Solidity在线编译器remix IDE进行测试。直接打开浏览器,输入http://remix.ethereum.org

图 1
点击“+”按钮,然后输入Solidity智能合约文件名:test3.sol

test3.sol的代码如下:

pragma solidity ^0.4.0; 
contract A {
    
    
    address public temp1;
    uint256 public temp2;
    function three_call(address addr) public {
    
    
            addr.call(bytes4(keccak256("test()")));                 // 情况1
            //addr.delegatecall(bytes4(keccak256("test()")));       // 情况2
            //addr.callcode(bytes4(keccak256("test()")));           // 情况3   
    }
} 

contract B {
    
    
    address public temp1;
    uint256 public temp2;    
    function test() public  {
    
    
            temp1 = msg.sender;        temp2 = 100;    
    }
}

图 2
点击图2中的Solidity按钮,就会弹出左边的几个功能按钮。

图 3
点击图3左边的“Solidity compiler”按钮,在test3.sol中输入上面的代码,然后点击“Compile test3.sol”

图 4
点击图4左边的“Deploy & run transactions”按钮,因为这里有A和B 2个合约,需要分别部署。先选择A合约,然后点击“Deploy”。对B合约进行同样的操作。这样A和B 2个合约就部署完成了。

下面我们来看看运行结果。运行过程是:先复制B合约的地址,粘贴到three_call函数的参数栏中,然后点击函数名即可。调用A合约的以太坊账号地址为:0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c

运行结果如下:
情况 1:call
调用call
情况 2 delegatecall
调用delegatecall
情况 3 callcode
调用callcode
从上面的运行结果,我们是不是已经看得很明白了。总结一下:
情况 1:call
A合约:
temp1 = 0
temp2 = 0

B合约:
temp1 = A合约地址
temp2 = 100

说明:call调用后内置变量 msg 的值会修改为调用者(A合约地址),执行环境为被调用者(B合约)的运行环境(运行环境指合约的 storage)

情况 2:delegatecall
A合约:
temp1 = 调用A合约的以太坊账号地址
temp2 = 100

B合约:
temp1 = 0
temp2 = 0

说明:delegatecall调用后内置变量 msg 的值不会修改为调用者(A合约地址),但执行环境为调用者(A合约)的运行环境

情况 3:callcode
A合约:
temp1 = A合约地址
temp2 = 100

B合约:
temp1 = 0
temp2 = 0

说明:callcode调用后内置变量 msg 的值会修改为调用者(A合约地址),但执行环境为调用者(A合约)的运行环境。

另外,以太坊的go版本源代码可从下面的地址下载 https://github.com/ethereum/go-ethereum 。但我用国内的网络试了很多遍都下载不成功,后面还是要用梯子才行。为方便大家,我把以太坊go-ethereum源码(v1.9.10)放到百度网盘方便大家下载:
https://pan.baidu.com/s/1frOZuMxdp5IVaY94ZdoN-A#list/path=%2F%E6%88%91%E7%9A%84%E5%85%B1%E4%BA%AB%E7%BD%91%E7%9B%98%2F%E4%BB%A5%E5%A4%AA%E5%9D%8A

猜你喜欢

转载自blog.csdn.net/powervip/article/details/104330170