本文主要是介绍智能合约的4种调用方式:call、callcode、delegatecall、staticcall,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
智能合约的4种调用方式:call、callcode、delegatecall、staticcall
资料来源:
以太坊 - 深入浅出虚拟机 以太坊 - 深入浅出虚拟机 | 登链社区 | 区块链技术社区虚拟机用来执行以太坊上的交易,更改以太坊状态。交易分两种:普通交易和智能合约交易。在执行交易时需要支付油费。智能合约之间的调用有四种方式https://learnblockchain.cn/2019/04/09/easy-evm/
1 四种合约调用方式
合约调用合约有下面4种方式:
- CALL
- CALLCODE 官方已经废弃CALLCODE了
- DELEGATECALL
- STATICCALL
2 CALL vs. CALLCODE
CALL和CALLCODE的区别在于:代码执行的上下文环境不同。
具体来说,CALL修改的是被调用者的storage,而CALLCODE修改的是调用者的storage。
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++;
}
}
3 CALLCODE 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错误。
这篇关于智能合约的4种调用方式:call、callcode、delegatecall、staticcall的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!