// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {MulticallFailed} from "../libs/Errors.sol"; /// @notice Collection of Multicall utilities. Fork of Multicall3: /// https://github.com/mds1/multicall/blob/master/src/Multicall3.sol abstract contract MultiCallable { struct Call { bool allowFailure; bytes callData; } struct Result { bool success; bytes returnData; } /// @notice Aggregates a few calls to this contract into one multicall without modifying `msg.sender`. function multicall(Call[] calldata calls) external returns (Result[] memory callResults) { uint256 amount = calls.length; callResults = new Result[](amount); Call calldata call_; for (uint256 i = 0; i < amount;) { call_ = calls[i]; Result memory result = callResults[i]; // We perform a delegate call to ourselves here. Delegate call does not modify `msg.sender`, so // this will have the same effect as if `msg.sender` performed all the calls themselves one by one. // solhint-disable-next-line avoid-low-level-calls (result.success, result.returnData) = address(this).delegatecall(call_.callData); // solhint-disable-next-line no-inline-assembly assembly { // Revert if the call fails and failure is not allowed // `allowFailure := calldataload(call_)` and `success := mload(result)` if iszero(or(calldataload(call_), mload(result))) { // Revert with `0x4d6a2328` (function selector for `MulticallFailed()`) mstore(0x00, 0x4d6a232800000000000000000000000000000000000000000000000000000000) revert(0x00, 0x04) } } unchecked { ++i; } } } }