智能合约开发

call、delegatecall 和 callcode 的区别

2021-08-30  本文已影响0人  张亚伦

汇总:
call: 调用后内置变量 msg 的值修改为调用者,执行环境为被调用者的运行环境(合约的 storage),最常用的调用方式。
delegatecall: 调用后内置变量 msg 的值不会修改为调用者(注:会改为以太坊账户的地址),但执行环境为调用者的运行环境。
callcode【v0.5.0时已禁用】: 调用后内置变量 msg 的值修改为调用者,但执行环境为调用者的运行环境。

  1. 准备环境
    示例合约代码:
pragma solidity ^0.4.0; 
contract A {    
    address public temp1;    
    uint256 public temp2;    
    function three_call(address addr) public {     
        // 1     
        addr.call(bytes4(keccak256("test()")));  
        // 2  
        //addr.delegatecall(bytes4(keccak256("test()")));
        // 3 
        //addr.callcode(bytes4(keccak256("test()"))); 
           
    } } 
contract B {    
    address public temp1;    
    uint256 public temp2;    
    function test() public  {        
        temp1 = msg.sender;        
        temp2 = 100;    
    } 
}
  1. 部署
    部署合约A,B。

  2. 测试

call

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

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

delegatecall
合约A:
temp1 = 调用合约A的以太坊账号地址
temp2 = 100
合约B:
temp1 = 0
temp2 = 0
说明:delegatecall调用后内置变量 msg 的值不会修改为调用者(合约A的地址),而是caller的账户地址,但执行环境为调用者(合约A)的运行环境

注意

上述的示例合约为v0.4.0,从v0.5.0之后有了一些变化,如下:

示例合约代码:

pragma solidity ^0.5.0; 
contract A {    
    address public temp1;    
    uint256 public temp2;    
    function three_call(address addr) public {     
        // 1     
        // addr.call(bytes4(keccak256("test()"))); 
        addr.call(abi.encodeWithSignature("test()")); 
        // 2  
        // addr.delegatecall(abi.encodeWithSignature("test()")); 
        // 3  depreated
        // addr.callcode(abi.encodeWithSignature("test()")); 
           
    } } 
contract B {    
    address public temp1;    
    uint256 public temp2;    
    function test() public  {        
        temp1 = msg.sender;        
        temp2 = 100;    
    } 
}
上一篇下一篇

猜你喜欢

热点阅读