interface IMulticall { /// @notice Takes an array of abi-encoded call data, delegatecalls itself with each calldata, and returns the abi-encoded result /// @dev Reverts if any delegatecall reverts /// @param data The abi-encoded data /// @returns results The abi-encoded return values function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results);
/// @notice OPTIONAL. Takes an array of abi-encoded call data, delegatecalls itself with each calldata, and returns the abi-encoded result /// @dev Reverts if any delegatecall reverts /// @param data The abi-encoded data /// @param values The effective msg.values. These must add up to at most msg.value /// @returns results The abi-encoded return values function multicallPayable(bytes[] calldata data, uint256[] values) external payable virtual returns (bytes[] memory results); }
multicallPayable 是可选的,因为由于 msg.value,它并不总是可行的。
以下是最为简陋的实现方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
pragma solidity ^0.8.0;
/// Derived from OpenZeppelin's implementation 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; } }