以太坊智能合约中函数调用三种方法(很重要!!!)

外部调用: sendTransaction/call

函数调用一般分外部调用和内部调用两种, 外部调用是通过JSON-RPC接口实现对合约函数的调用, 有3种调用方式:

testInstance.testFunc.sendTransaction();
testInstance.testFunc();
testInstance.testFunc.call();

区别如下:

  • testInstance.testFunc.sendTransaction() ; 会创建一个交易,调用之后会返回一个交易hash值,它会广播到网络,等待矿工打包, 它会消耗gas。
  • testInstance.testFunc.call() ; 它完全是一个本地调用,不会向区块链网络广播任何东西,它的返回值完全取决于 testFunc 方法的代码,不会消耗gas。
  • testInstance.testFunc() ; 它会比较特殊,由于有constant标识的方法不会修改状态变量,所以它不会被编译器执行。所以,如果testFunc() 有constant标识,它并不会被编译器执行,web3.js会执行call()的本地操作。相反如果没有constant标识,会执行sendTransaction()操作。

测试代码如下:

pragma solidity ^0.4.12;
contract Test {
 uint public testMem;

 function testFunc1() returns (string resMes){
 testMem++;
 resMes = "try to modify testMem,but has no constant label";
 }

 function testFunc2() constant returns (string resMes){
 testMem--;
 resMes = "try to modify testMem and has constant label";
 }
}

内部调用: call,callcode,delegatecall

内部调用是指合约内调用其他合约的函数. 除了直接调用函数,还可以通过call,callcode,delegatecall的方式调用其他合约的函数,区别如下:

  • CALL:是在 被调用者 的上下文中执行,只能修改被调用者的storage;
  • CALLCODE和DELEGATECALL: 是在 调用者 的上下文中执行, 可以修改调用者的storage;
  • CALLCODE 阻止msg.sender和msg.value传递; 而DELEGATECALL不阻止;
    • 在A的函数中,B.callcode(c的函数): c看到msg.sender是B;
    • 在A的函数中,B.delegatecall(c的函数): c看到msg.sender是A;

合约示例如下:

    contract D {
     uint public n;
     address public sender;
     function callSetN(address _e, uint _n) {
            // E的 storage被修改,D未修改
     _e.call(bytes4(sha3("setN(uint256)")), _n); 
     }
     function callcodeSetN(address _e, uint _n) {
            // D的 storage被修改, E未修改
     _e.callcode(bytes4(sha3("setN(uint256)")), _n); 
     }
     function delegatecallSetN(address _e, uint _n) {
            // D的storage被修改, E未修改
     _e.delegatecall(bytes4(sha3("setN(uint256)")), _n); 
     }
    }
    contract E {
     uint public n;
     address public sender;
     function setN(uint _n) {
     n = _n;
     sender = msg.sender;
     // D通过callcodeSetN调用, msg.sender是D . E的storage不会更新
     // 通过C.foo()调用,msg.sender是C . E的storage不会更新
     }
    }
    contract C {
     function foo(D _d, E _e, uint _n) {
     _d.delegatecallSetN(_e, _n);
     }
    }


转载链接:https://www.jianshu.com/p/f33df6fb3ce4
來源:简书

猜你喜欢

转载自blog.csdn.net/weixin_43343144/article/details/85240235