ERC-6357: 单合约多重委托调用
允许 EOA 在单个交易中调用智能合约的多个函数
Authors | Gavin John (@Pandapip1) |
---|---|
Created | 2023-01-18 |
Last Call Deadline | 2023-11-10 |
摘要
此 EIP 标准化了一个包含单个函数 multicall
的接口,允许 EOA 在单个交易中调用智能合约的多个函数,并且如果任何调用失败,则回滚所有调用。
动机
目前,为了转移若干 ERC-721 NFT,需要提交与正在转移的 NFT 数量相等的交易。这浪费了用户的资金,因为他们需要为每个转移的 NFT 支付 21000 gas 费。
规范
本文档中的关键词 “MUST”,“MUST NOT”,“REQUIRED”,“SHALL”,“SHALL NOT”,“SHOULD”,“SHOULD NOT”,“ RECOMMENDED”,“NOT RECOMMENDED”,“MAY” 和 “OPTIONAL” 应按照 RFC 2119 和 RFC 8174 中的描述进行解释。
实现此 EIP 的合约必须实现以下接口:
pragma solidity ^0.8.0;
interface IMulticall {
/// @notice 接受 abi 编码的调用数据数组,使用每个调用数据委托调用自身,并返回 abi 编码的结果
/// @dev 如果任何委托调用回滚,则回滚
/// @param data abi 编码的数据
/// @returns results abi 编码的返回值
function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results);
/// @notice 可选。接受 abi 编码的调用数据数组,使用每个调用数据委托调用自身,并返回 abi 编码的结果
/// @dev 如果任何委托调用回滚,则回滚
/// @param data abi 编码的数据
/// @param values 有效的 msg.values。这些加起来必须最多为 msg.value
/// @returns results abi 编码的返回值
function multicallPayable(bytes[] calldata data, uint256[] values) external payable virtual returns (bytes[] memory results);
}
Rationale
multicallPayable
是可选的,因为它并非总是可行,因为 msg.value
的拆分。
向后兼容性
这与大多数现有的 multicall 函数兼容。
测试用例
以下 JavaScript 代码,使用 Ethers 库,应原子地将 amt
单位的 ERC-20 token 转移到 addressA
和 addressB
。
await token.multicall(await Promise.all([
token.interface.encodeFunctionData('transfer', [ addressA, amt ]),
token.interface.encodeFunctionData('transfer', [ addressB, amt ]),
]));
参考实现
pragma solidity ^0.8.0;
/// 源自 OpenZeppelin 的实现
abstract contract Multicall is IMulticall {
function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {
results = new bytes[](data.length);
for (uint256 i = 0; i < data.length; i++) {
(bool success, bytes memory returndata) = address(this).delegatecall(data);
require(success);
results[i] = returndata;
}
return results;
}
}
安全考虑
只有当合约能够支持 multicallPayable
时才应该使用它。 简单地尝试实现它可能会允许攻击者使用相同的以太多次调用 payable 函数。
版权
版权和相关权利通过 CC0 放弃。
Citation
Please cite this document as:
Gavin John (@Pandapip1), "ERC-6357: 单合约多重委托调用 [DRAFT]," Ethereum Improvement Proposals, no. 6357, January 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-6357.