美文网首页智能合约开发
call、delegatecall 和 callcode 的区别

call、delegatecall 和 callcode 的区别

作者: 张亚伦 | 来源:发表于2021-08-30 17:19 被阅读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. 测试

    • 方案1: addr.call(bytes4(keccak256("test()")));
      结果如下:
    call

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

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

    • 方案2: addr.delegatecall(bytes4(keccak256("test()")));
      结果如下:
    delegatecall
    合约A:
    temp1 = 调用合约A的以太坊账号地址
    temp2 = 100
    合约B:
    temp1 = 0
    temp2 = 0
    说明:delegatecall调用后内置变量 msg 的值不会修改为调用者(合约A的地址),而是caller的账户地址,但执行环境为调用者(合约A)的运行环境
    • 方案3: addr.callcode(bytes4(keccak256("test()")));
      结果如下:
      callcode
      合约A:
      temp1 =合约A的地址
      temp2 = 100
      合约B:
      temp1 = 0
      temp2 = 0
      说明:callcode调用后内置变量 msg 的值会修改为调用者(合约A的地址),但执行环境为调用者(合约A)的运行环境。

    注意

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

    • x.call(bytes4(keccak256("f(uint256)")), a, b) to x.call(abi.encodeWithSignature("f(uint256)", a, b))
    • Function callcode is now disallowed (in favor of delegatecall). It is still possible to use it via inline assembly.

    示例合约代码:

    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;    
        } 
    }
    

    相关文章

      网友评论

        本文标题:call、delegatecall 和 callcode 的区别

        本文链接:https://www.haomeiwen.com/subject/vrhoiltx.html