solidity 学习笔记(5)call 函数

call() 方法

call()是一个底层的接口,用来向一个合约发送消息,也就是说如果你想实现自己的消息传递,可以使用这个函数。函数支持传入任意类型的任意参数,并将参数打包成32字节,相互拼接后向合约发送这段数据。

简单说 根据地址调用指定合约的方法。

pragma solidity ^0.4.24;
 
contract cat{
    
    function eat(uint a) public view returns(uint){
        return a;
    }
    
}
 
 
contract Animal{
    
    cat c;
    constructor(address _add){
        c = cat(_add);
    }
   
   function test()public view returns(uint) { //普通实例化合约调用
       return c.eat(1);
   }
   
   function test2()public view returns(bool) {  //通过call方法调用
       return c.call(bytes32(keccak256("eat()")),2);//通过bytes32(keccak256("eat()"指定方法,后面的是参数
} }

由于向另一个合约发送数据时,找不到对应的方法签名,会默认调用fallback()函数,所以我们可以通过这个来看看call()传的具体数据。

 
    bytes fail;
    
    function(){
        fail = msg.data;
    }

如果第一个参数刚好是四个字节,会认为这四个字节指定的是函数签名的序号值,生成方式参见ABI协议的函数选择器。如果你只是想传个参数值,而不是想指定一个函数序号,应避免第一个参数刚好是四个字节。

call()的返回结果是一个bool,表示是否成功的调用,或者是失败引起了EVM异常。该方法无法直接访问函数返回结果(因为需要事前知道编码和返回结果大小)。

call()的返回结果即使成功,并不能说操作成功了,只是没有出现异常,有可能调用到了fallback()函数。

delegatecall()

calldelegatecall的功能类似,区别仅在于后者仅使用给定地址的代码,其它信息则使用当前合约(如存储,余额等等)。

函数的设计目的是为了使用存储在另一个合约的库代码。

所以开发者在提供这样的库时,就要如何安排存储来达到这样的目的。

二者执行代码的上下文环境的不同,当使用call调用其它合约的函数时,代码是在被调用的合约的环境里执行,对应的,使用delegatecall进行函数调用时代码则是在调用函数的合约的环境里执行。

猜你喜欢

转载自www.cnblogs.com/gzhlt/p/9997798.html