智能合约的4种调用方式:call、callcode、delegatecall、staticcall 资料来源: 以太坊 – 深入浅出虚拟机 以太坊 – 深入浅出虚拟机 | 登链社区 | 区块链技术社区虚拟机用来执行以太坊上的交易,更改以太坊状态。交易分两种:普通交易和智能合约交易。在执行交易时需要支付油费。智能合约之间的调用有四种方式

pragma solidity ^0.4.25; contract A { int public x; function inc_call(address _contractAddress) public { _contractAddress.call(bytes4(keccak256(“inc()”))); } function inc_callcode(address _contractAddress) public { _contractAddress.callcode(bytes4(keccak256(“inc()”))); } } contract B { int public x; function inc() public { x++; } } 3CALLCODE vs. DELEGATECALL 实际上,可以认为DELEGATECALL是CALLCODE的一个bugfix版本,官方已经不建议使用CALLCODE了。 CALLCODE和DELEGATECALL的区别在于:msg.sender不同。 具体来说,DELEGATECALL会一直使用原始调用者的地址,而CALLCODE不会。

我们还是写一段代码来验证我们的理解: pragma solidity ^0.4.25; contract A { int public x; function inc_callcode(address _contractAddress) public { _contractAddress.callcode(bytes4(keccak256(“inc()”))); } function inc_delegatecall(address _contractAddress) public { _contractAddress.delegatecall(bytes4(keccak256(“inc()”))); } } contract B { int public x; event senderAddr(address); function inc() public { x++; emit senderAddr(msg.sender); } } 4 STATICCALL STATICCALL放在这里似乎有滥竽充数之嫌,因为目前Solidity中并没有一个low level API可以直接调用它,仅仅是计划将来在编译器层面把调用view和pure类型的函数编译成STATICCALL指令。 view类型的函数表明其不能修改状态变量,而pure类型的函数则更加严格,连读取状态变量都不允许。 目前是在编译阶段来检查这一点的,如果不符合规定则会出现编译错误。如果将来换成STATICCALL指令,就可以完全在运行时阶段来保证这一点了,你可能会看到一个执行失败的交易。 话不多说,我们就先看看STATICCALL的实现代码吧: 可以看到,解释器增加了一个readOnly属性,STATICCALL会把该属性置为true,如果出现状态变量的写操作,则会返回一个errWriteProtection错误。