Ethereum调用机制总结call/delegatecall/callcode/send/transfer

in ethereum •  6 years ago  (edited)

Ethereum中涉及各种类型的方法调用。一个编程中常用的call概念,可能为Ethereum Vitrual Machine(EVM)内的call,又可能为EVM外的call,又涉及诸如Message/Transaction等基本概念;同时还包括call/delegatecall/callcode/send/transfer/sendTransaction等等方法。

对这些调用机制及基本概念的说明散落在 solidity文档 、黄皮书、白皮书 中,初学者容易搞晕。这里对这些基本概念、调用机制及用法做一下整体梳理。

Ethereum调用机制总结脑图

PDF版本下载:Ethereum调用机制总结pdf版本

PNG版本下载:Ethereum调用机制总结png版本

示例代码下载:测试代码

pragma solidity ^ 0.4.18;

contract A {
    uint public var2;
    uint public var1;
    B b1;
    address addrB;   
    function A() public {
        b1 = new B();
        addrB=address(b1);
    }

    function callSet(address addr, uint param) public returns(uint) {
        //addr.call(bytes4(keccak256("set(uint)")), param); //使用了uint,调用不生效。应当使用uint256; uint是uint256的昵称,但在ABI调用时候,只能使用长类型。
        
        //使用address.call
        addr.call(bytes4(keccak256("set(uint256)")), param); //call 使用的是被调用者的存储,因此改变的是B.var1值
        
        //使用实例方式,可以直接采用callee.method形式调用,从而直接获取函数返回值
        /*
        B b2 = B(addr);  
        uint result = b2.set(param);
        return result;
        */
        
        //使用 new B()方式方式调用 
        // uint  b1=b1.set(param);  
        // addrB.call(bytes4(keccak256("set(uint256)")), param);
        
        return 1;
    }

    function delegatecallSet(address addr, uint param) {
        //addr.delegatecall(bytes4(keccak256("set(uint)")), param); //使用了uint,调用不生效。应当使用uint256; uint是uint256的昵称,但在ABI调用时候,只能使用长类型。
        addr.delegatecall(bytes4(keccak256("set(uint256)")), param); //delegatecall和callcode都是使用调用者的存储,特别要注意调用者和被调用者合约变量定义顺序,目前改变的是A.var2的值。
        B b2 = B(addr);  //使用实例方式,可以直接采用callee.method形式调用,从而直接获取函数返回值
        uint result = b2.set(param);
        // uint  b1=b1.set(param);  
        // addrB.call(bytes4(keccak256("set(uint256)")), param);        
    }

    function callcodeSet(address addr, uint param) {
        addr.callcode(bytes4(keccak256("set(uint256)")), param);
    }

    function getVar1() public view returns(uint) {
        return var1;
    }

    function getVar2() public view returns(uint) {
        return var2;
    }
    
    function getAddr() public view returns(address) {
        return addrB;
    }    
}

contract B {
    uint public var1;
    event MyEvent(uint param, uint result);

    function set(uint param) public returns(uint) {
        var1 = param;
        MyEvent(param, 1);
        return param;
    }
}

原文:http://www.yeeach.com/post/1340

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Congratulations @chuanliang! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 2 years!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Vote for @Steemitboard as a witness to get one more award and increased upvotes!