出家如初,成佛有余

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

Posted in 技术相关 by chuanliang on 2018/04/02

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

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

Ethereum调用机制总结

PDF版本:Ethereum调用机制总结

PNG版本:Ethereum调用机制总结

示例代码:测试代码下载

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

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

You are commenting using your WordPress.com account. Log Out /  更改 )

Google+ photo

You are commenting using your Google+ account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

Connecting to %s

%d 博主赞过: