其实,智能合约实际上就是由Solidity代码编译后的程序。编译后的程序,由以太坊的EVM执行。
在以太坊中,Solidity编写的智能合约经过编译后会生成一串十六进制的字节码,创建后进行调用时,也需要将调用的函数(function)名称和参数转化为一串十六进制字节码写进交易中。当用户通过发送eth_sendTransation
或者eth_call
创建或者调用智能合约时,就在交易(Transaction)的data字段填入这个十六进制码。
先上代码,下面有5个合约,其中后面4个都是Counter合约的inc方法。
contract Counter
{
uint public count = 10;
function inc(uint num) public returns (uint)
{
return count += num;
}
}
contract CallCounter
{
uint public count = 20;
function callByAddr(address addr) public returns (uint)
{
return Counter(addr).inc(2);
}
}
contract Caller_by_call
{
uint count = 20;
function callByAddr(address addr) public returns (bool)
{
bytes4 methodId = bytes4(keccak256("inc(uint256)"));
return addr.call(methodId, 2);
}
}
contract Caller_by_delegatecall
{
uint count = 20;
function callByAddr(address addr) public returns(bool)
{
bytes4 methodId = bytes4(keccak256("inc(uint256)"));
return addr.delegatecall(methodId, 2);
}
}
contract Caller_by_delegatecall_without_count
{
function callByAddr(address addr) public returns(bool)
{
bytes4 methodId = bytes4(keccak256("inc(uint256)"));
return addr.delegatecall(methodId, 2);
}
}
CallCounter中的Counter(addr).inc(2)
是种高级别的调用方式。可以获取到返回结果,返回值为12(即Conter的inc函数的返回值)。
其他的调用方式
除了上面的方式,solidity还提供了3种“低级别”的调用方式
- address.call(...)
- address.callcode(...) 已弃用,不介绍了
- address.delegatecall(...)
address.call(...)
- address.call(...)的返回是bool型的变量,通过底层的call来调用其他智能合约是不能获取返回值。
address.delegatecall(...)
- 当调用address.delegatecall(...)结束后,Counter合约中的count值没有变化,依旧是10,也就是说,delegatecall通过别的智能合约的方法,修改自己的智能合约状态。
最后一个智能合约Caller_by_delegatecall_without_count
- 没有count变量,如果执行,则智能的创建了一个count,结果为2。