// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; /** * @title Multicall * @notice Aggregate multiple calls in a single transaction * @dev Based on Uniswap V3 Multicall */ contract Multicall { struct Call { address target; bytes callData; } struct Result { bool success; bytes returnData; } /** * @notice Aggregate multiple calls * @param calls Array of calls to execute * @return returnData Array of return data for each call */ function aggregate(Call[] memory calls) public returns (bytes[] memory returnData) { returnData = new bytes[](calls.length); for (uint256 i = 0; i < calls.length; i++) { (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData); require(success, "Multicall: call failed"); returnData[i] = ret; } } /** * @notice Aggregate multiple calls, allowing failures * @param requireSuccess If true, require all calls to succeed * @param calls Array of calls to execute * @return returnData Array of results with success flags and return data for each call */ function tryAggregate(bool requireSuccess, Call[] memory calls) public returns (Result[] memory returnData) { returnData = new Result[](calls.length); for (uint256 i = 0; i < calls.length; i++) { (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData); if (requireSuccess) { require(success, "Multicall: call failed"); } returnData[i] = Result(success, ret); } } /** * @notice Aggregate multiple calls with gas limit * @param calls Array of calls to execute * @param gasLimit Gas limit for each call * @return returnData Array of return data for each call */ function aggregateWithGasLimit(Call[] memory calls, uint256 gasLimit) public returns (bytes[] memory returnData) { returnData = new bytes[](calls.length); for (uint256 i = 0; i < calls.length; i++) { (bool success, bytes memory ret) = calls[i].target.call{gas: gasLimit}(calls[i].callData); require(success, "Multicall: call failed"); returnData[i] = ret; } } /** * @notice Get block hash for a specific block * @param blockNumber Block number * @return blockHash Block hash */ function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) { blockHash = blockhash(blockNumber); } /** * @notice Get current block timestamp * @return timestamp Current block timestamp */ function getCurrentBlockTimestamp() public view returns (uint256 timestamp) { timestamp = block.timestamp; } /** * @notice Get current block difficulty * @return difficulty Current block difficulty */ function getCurrentBlockDifficulty() public view returns (uint256 difficulty) { difficulty = block.difficulty; } /** * @notice Get current block gas limit * @return gaslimit Current block gas limit */ function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) { gaslimit = block.gaslimit; } /** * @notice Get current block coinbase * @return coinbase Current block coinbase */ function getCurrentBlockCoinbase() public view returns (address coinbase) { coinbase = block.coinbase; } /** * @notice Get current block number * @return blockNumber Current block number */ function getCurrentBlockNumber() public view returns (uint256 blockNumber) { blockNumber = block.number; } /** * @notice Get current chain ID * @return chainid Current chain ID */ function getChainId() public view returns (uint256 chainid) { chainid = block.chainid; } }