在之前的文章中,已经详细介绍了delegatecall和call的用法, 原文: EIP1967-实现可升级智能合约
delegatecall:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
// NOTE: Deploy this contract first
contract B {
// NOTE: storage layout must be the same as contract A
uint public num;
address public sender;
uint public value;
function setVars(uint _num) public payable {
num = _num;
sender = msg.sender;
value = msg.value;
}
}
contract A {
uint public num;
address public sender;
uint public value;
function setVars(address _contract, uint _num) public payable {
// A's storage is set, B is not modified.
(bool success, bytes memory data) = _contract.delegatecall(
abi.encodeWithSignature("setVars(uint256)", _num)
);
}
}
调用合约A的setVars函数,setVars合约内会以delegatecall的方式调用合约B, 更确切地说是合约A将合约B的setVars函数代码加载到合约A的运行环境,因此,就很容易理解setVars修改的是合约A中的数据,而不是合约B中的数据了。


call
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
// NOTE: Deploy this contract first
contract B {
// NOTE: storage layout must be the same as contract A
uint public num;
address public sender;
uint public value;
function setVars(uint _num) public payable {
num = _num;
sender = msg.sender;
value = msg.value;
}
}
contract A {
uint public num;
address public sender;
uint public value;
function setVars(address _contract, uint _num) public payable {
// A's storage is set, B is not modified.
(bool success, bytes memory data) = _contract.call(
abi.encodeWithSignature("setVars(uint256)", _num)
);
}
}

文章对比了delegatecall和call在以太坊智能合约中的使用,解释了delegatecall如何让合约A在自己的存储空间执行合约B的函数,从而实现数据修改在A而非B中,而call则不会修改调用者的存储状态。示例代码展示了两种调用方式的实现。

603

被折叠的 条评论
为什么被折叠?



