From 5f5d270aa9f8a7f893497c65e31b2ed9c900ae52 Mon Sep 17 00:00:00 2001 From: nicholaspai Date: Sun, 4 May 2025 13:59:55 -0400 Subject: [PATCH 1/3] feat: Create PermissionedMulticall3 We're running into a frustrating situation where a contract like `SP1Helios.update()` can only be called by a permissioned EOA but we'd like to batch this call with an unpermissioned call to `Universal_SpokePool.execute()`. This doesn't work because there is no way to batch the `update()` call from an EOA with a contract call. Therefore if we had a function like this PermissionedMulticall3 that we could whitelist as a `SP1Helios.update()` caller, then we could batch it with `execute()` --- contracts/external/PermissionedMulticall3.sol | 254 ++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 contracts/external/PermissionedMulticall3.sol diff --git a/contracts/external/PermissionedMulticall3.sol b/contracts/external/PermissionedMulticall3.sol new file mode 100644 index 000000000..73c95d135 --- /dev/null +++ b/contracts/external/PermissionedMulticall3.sol @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; // Bumped version + +/** + * This is a simple fork of Multicall3 (the version found in this repo) that makes the contract Ownable + * and adds a whitelist of addresses that are allowed to call the contract's external functions. + **/ + +/// @title PermissionedMulticall3 +/// @notice Aggregate results from multiple function calls but only allows a whitelisted set of msg.senders. +/// @dev This contract is designed to be used as part of a permissioned system where this contract can be whitelisted +/// to call other contracts on behalf of the whitelisted senders. The benefit is that the whitelisted senders +/// can still batch call permissioned functions with unpermissioned functions by going through this contract. +/// @dev Multicall & Multicall2 backwards-compatible +/// @dev Aggregate methods are marked `payable` to save 24 gas per call +/// @author Michael Elliot +/// @author Joshua Levine +/// @author Nick Johnson +/// @author Andreas Bigger +/// @author Matt Solomon +contract PermissionedMulticall3 { + struct Call { + address target; + bytes callData; + } + + struct Call3 { + address target; + bool allowFailure; + bytes callData; + } + + struct Call3Value { + address target; + bool allowFailure; + uint256 value; + bytes callData; + } + + struct Result { + bool success; + bytes returnData; + } + + /// @notice Backwards-compatible call aggregation with Multicall + /// @param calls An array of Call structs + /// @return blockNumber The block number where the calls were executed + /// @return returnData An array of bytes containing the responses + function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) { + blockNumber = block.number; + uint256 length = calls.length; + returnData = new bytes[](length); + Call calldata call; + for (uint256 i = 0; i < length; ) { + bool success; + call = calls[i]; + (success, returnData[i]) = call.target.call(call.callData); + require(success, "Multicall3: call failed"); + unchecked { + ++i; + } + } + } + + /// @notice Backwards-compatible with Multicall2 + /// @notice Aggregate calls without requiring success + /// @param requireSuccess If true, require all calls to succeed + /// @param calls An array of Call structs + /// @return returnData An array of Result structs + function tryAggregate(bool requireSuccess, Call[] calldata calls) + public + payable + returns (Result[] memory returnData) + { + uint256 length = calls.length; + returnData = new Result[](length); + Call calldata call; + for (uint256 i = 0; i < length; ) { + Result memory result = returnData[i]; + call = calls[i]; + (result.success, result.returnData) = call.target.call(call.callData); + if (requireSuccess) require(result.success, "Multicall3: call failed"); + unchecked { + ++i; + } + } + } + + /// @notice Backwards-compatible with Multicall2 + /// @notice Aggregate calls and allow failures using tryAggregate + /// @param calls An array of Call structs + /// @return blockNumber The block number where the calls were executed + /// @return blockHash The hash of the block where the calls were executed + /// @return returnData An array of Result structs + function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) + public + payable + returns ( + uint256 blockNumber, + bytes32 blockHash, + Result[] memory returnData + ) + { + blockNumber = block.number; + blockHash = blockhash(block.number); + returnData = tryAggregate(requireSuccess, calls); + } + + /// @notice Backwards-compatible with Multicall2 + /// @notice Aggregate calls and allow failures using tryAggregate + /// @param calls An array of Call structs + /// @return blockNumber The block number where the calls were executed + /// @return blockHash The hash of the block where the calls were executed + /// @return returnData An array of Result structs + function blockAndAggregate(Call[] calldata calls) + public + payable + returns ( + uint256 blockNumber, + bytes32 blockHash, + Result[] memory returnData + ) + { + (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls); + } + + /// @notice Aggregate calls, ensuring each returns success if required + /// @param calls An array of Call3 structs + /// @return returnData An array of Result structs + function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) { + uint256 length = calls.length; + returnData = new Result[](length); + Call3 calldata calli; + for (uint256 i = 0; i < length; ) { + Result memory result = returnData[i]; + calli = calls[i]; + (result.success, result.returnData) = calli.target.call(calli.callData); + assembly { + // Revert if the call fails and failure is not allowed + // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` + if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { + // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) + mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) + // set data offset + mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) + // set length of revert string + mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017) + // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) + mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000) + revert(0x00, 0x64) + } + } + unchecked { + ++i; + } + } + } + + /// @notice Aggregate calls with a msg value + /// @notice Reverts if msg.value is less than the sum of the call values + /// @param calls An array of Call3Value structs + /// @return returnData An array of Result structs + function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) { + uint256 valAccumulator; + uint256 length = calls.length; + returnData = new Result[](length); + Call3Value calldata calli; + for (uint256 i = 0; i < length; ) { + Result memory result = returnData[i]; + calli = calls[i]; + uint256 val = calli.value; + // Humanity will be a Type V Kardashev Civilization before this overflows - andreas + // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256 + unchecked { + valAccumulator += val; + } + (result.success, result.returnData) = calli.target.call{ value: val }(calli.callData); + assembly { + // Revert if the call fails and failure is not allowed + // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` + if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { + // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) + mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) + // set data offset + mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) + // set length of revert string + mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017) + // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) + mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000) + revert(0x00, 0x84) + } + } + unchecked { + ++i; + } + } + // Finally, make sure the msg.value = SUM(call[0...i].value) + require(msg.value == valAccumulator, "Multicall3: value mismatch"); + } + + /// @notice Returns the block hash for the given block number + /// @param blockNumber The block number + function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) { + blockHash = blockhash(blockNumber); + } + + /// @notice Returns the block number + function getBlockNumber() public view returns (uint256 blockNumber) { + blockNumber = block.number; + } + + /// @notice Returns the block coinbase + function getCurrentBlockCoinbase() public view returns (address coinbase) { + coinbase = block.coinbase; + } + + /// @notice Returns the block difficulty + function getCurrentBlockDifficulty() public view returns (uint256 difficulty) { + difficulty = block.difficulty; + } + + /// @notice Returns the block gas limit + function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) { + gaslimit = block.gaslimit; + } + + /// @notice Returns the block timestamp + function getCurrentBlockTimestamp() public view returns (uint256 timestamp) { + timestamp = block.timestamp; + } + + /// @notice Returns the (ETH) balance of a given address + function getEthBalance(address addr) public view returns (uint256 balance) { + balance = addr.balance; + } + + /// @notice Returns the block hash of the last block + function getLastBlockHash() public view returns (bytes32 blockHash) { + unchecked { + blockHash = blockhash(block.number - 1); + } + } + + /// @notice Gets the base fee of the given block + /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain + function getBasefee() public view returns (uint256 basefee) { + basefee = block.basefee; + } + + /// @notice Returns the chain id + function getChainId() public view returns (uint256 chainid) { + chainid = block.chainid; + } +} From 624454e1f6aa869871d8b197e2fae9a9e3a6ec9b Mon Sep 17 00:00:00 2001 From: nicholaspai Date: Sun, 4 May 2025 14:08:03 -0400 Subject: [PATCH 2/3] Deploy --- deploy/112_deploy_permissioned_multicall3.ts | 16 + deployments/bsc/PermissionedMulticall3.json | 592 ++++++++++++++++++ .../8eea81dcd66c98bcacab463f809f2a48.json | 37 ++ 3 files changed, 645 insertions(+) create mode 100644 deploy/112_deploy_permissioned_multicall3.ts create mode 100644 deployments/bsc/PermissionedMulticall3.json create mode 100644 deployments/bsc/solcInputs/8eea81dcd66c98bcacab463f809f2a48.json diff --git a/deploy/112_deploy_permissioned_multicall3.ts b/deploy/112_deploy_permissioned_multicall3.ts new file mode 100644 index 000000000..c50aaf382 --- /dev/null +++ b/deploy/112_deploy_permissioned_multicall3.ts @@ -0,0 +1,16 @@ +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployer } = await hre.getNamedAccounts(); + + const instance = await hre.deployments.deploy("PermissionedMulticall3", { + from: deployer, + log: true, + skipIfAlreadyDeployed: true, + }); + await hre.run("verify:verify", { address: instance.address }); +}; + +module.exports = func; +func.tags = ["PermissionedMulticall3"]; diff --git a/deployments/bsc/PermissionedMulticall3.json b/deployments/bsc/PermissionedMulticall3.json new file mode 100644 index 000000000..5349b5f1c --- /dev/null +++ b/deployments/bsc/PermissionedMulticall3.json @@ -0,0 +1,592 @@ +{ + "address": "0x38015ddB8b34c84934Cff058F571349Cc7d4139d", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct PermissionedMulticall3.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "aggregate", + "outputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes[]", + "name": "returnData", + "type": "bytes[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowFailure", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct PermissionedMulticall3.Call3[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "aggregate3", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "internalType": "struct PermissionedMulticall3.Result[]", + "name": "returnData", + "type": "tuple[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bool", + "name": "allowFailure", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct PermissionedMulticall3.Call3Value[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "aggregate3Value", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "internalType": "struct PermissionedMulticall3.Result[]", + "name": "returnData", + "type": "tuple[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct PermissionedMulticall3.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "blockAndAggregate", + "outputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "internalType": "struct PermissionedMulticall3.Result[]", + "name": "returnData", + "type": "tuple[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "getBasefee", + "outputs": [ + { + "internalType": "uint256", + "name": "basefee", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "getBlockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getChainId", + "outputs": [ + { + "internalType": "uint256", + "name": "chainid", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockCoinbase", + "outputs": [ + { + "internalType": "address", + "name": "coinbase", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockDifficulty", + "outputs": [ + { + "internalType": "uint256", + "name": "difficulty", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockGasLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "gaslimit", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentBlockTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "getEthBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLastBlockHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "requireSuccess", + "type": "bool" + }, + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct PermissionedMulticall3.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "tryAggregate", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "internalType": "struct PermissionedMulticall3.Result[]", + "name": "returnData", + "type": "tuple[]" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "requireSuccess", + "type": "bool" + }, + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "internalType": "struct PermissionedMulticall3.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "tryBlockAndAggregate", + "outputs": [ + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "blockHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "returnData", + "type": "bytes" + } + ], + "internalType": "struct PermissionedMulticall3.Result[]", + "name": "returnData", + "type": "tuple[]" + } + ], + "stateMutability": "payable", + "type": "function" + } + ], + "transactionHash": "0x541a58a25a3184b1bc7606bafec5f50445ad7a82d40a9f20f10a6f2a599c0b03", + "receipt": { + "to": null, + "from": "0x9A8f92a830A5cB89a3816e3D267CB7791c16b04D", + "contractAddress": "0x38015ddB8b34c84934Cff058F571349Cc7d4139d", + "transactionIndex": 20, + "gasUsed": "791327", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x5ef391a594a50a49b61faa6bb168b9471bfce2198e9742f66ab41c69d60b2dd3", + "transactionHash": "0x541a58a25a3184b1bc7606bafec5f50445ad7a82d40a9f20f10a6f2a599c0b03", + "logs": [], + "blockNumber": 49092597, + "cumulativeGasUsed": "4316908", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "8eea81dcd66c98bcacab463f809f2a48", + "metadata": "{\"compiler\":{\"version\":\"0.8.23+commit.f704f362\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"returnData\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call3[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call3Value[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3Value\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"blockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBasefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"basefee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"getBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainid\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockCoinbase\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"coinbase\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockDifficulty\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"difficulty\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockGasLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gaslimit\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getEthBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryAggregate\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryBlockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Michael Elliot Joshua Levine Nick Johnson Andreas Bigger Matt Solomon \",\"details\":\"This contract is designed to be used as part of a permissioned system where this contract can be whitelisted to call other contracts on behalf of the whitelisted senders. The benefit is that the whitelisted senders can still batch call permissioned functions with unpermissioned functions by going through this contract.Multicall & Multicall2 backwards-compatibleAggregate methods are marked `payable` to save 24 gas per call\",\"kind\":\"dev\",\"methods\":{\"aggregate((address,bytes)[])\":{\"params\":{\"calls\":\"An array of Call structs\"},\"returns\":{\"blockNumber\":\"The block number where the calls were executed\",\"returnData\":\"An array of bytes containing the responses\"}},\"aggregate3((address,bool,bytes)[])\":{\"params\":{\"calls\":\"An array of Call3 structs\"},\"returns\":{\"returnData\":\"An array of Result structs\"}},\"aggregate3Value((address,bool,uint256,bytes)[])\":{\"params\":{\"calls\":\"An array of Call3Value structs\"},\"returns\":{\"returnData\":\"An array of Result structs\"}},\"blockAndAggregate((address,bytes)[])\":{\"params\":{\"calls\":\"An array of Call structs\"},\"returns\":{\"blockHash\":\"The hash of the block where the calls were executed\",\"blockNumber\":\"The block number where the calls were executed\",\"returnData\":\"An array of Result structs\"}},\"getBlockHash(uint256)\":{\"params\":{\"blockNumber\":\"The block number\"}},\"tryAggregate(bool,(address,bytes)[])\":{\"params\":{\"calls\":\"An array of Call structs\",\"requireSuccess\":\"If true, require all calls to succeed\"},\"returns\":{\"returnData\":\"An array of Result structs\"}},\"tryBlockAndAggregate(bool,(address,bytes)[])\":{\"params\":{\"calls\":\"An array of Call structs\"},\"returns\":{\"blockHash\":\"The hash of the block where the calls were executed\",\"blockNumber\":\"The block number where the calls were executed\",\"returnData\":\"An array of Result structs\"}}},\"title\":\"PermissionedMulticall3\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"aggregate((address,bytes)[])\":{\"notice\":\"Backwards-compatible call aggregation with Multicall\"},\"aggregate3((address,bool,bytes)[])\":{\"notice\":\"Aggregate calls, ensuring each returns success if required\"},\"aggregate3Value((address,bool,uint256,bytes)[])\":{\"notice\":\"Aggregate calls with a msg valueReverts if msg.value is less than the sum of the call values\"},\"blockAndAggregate((address,bytes)[])\":{\"notice\":\"Backwards-compatible with Multicall2Aggregate calls and allow failures using tryAggregate\"},\"getBasefee()\":{\"notice\":\"Gets the base fee of the given blockCan revert if the BASEFEE opcode is not implemented by the given chain\"},\"getBlockHash(uint256)\":{\"notice\":\"Returns the block hash for the given block number\"},\"getBlockNumber()\":{\"notice\":\"Returns the block number\"},\"getChainId()\":{\"notice\":\"Returns the chain id\"},\"getCurrentBlockCoinbase()\":{\"notice\":\"Returns the block coinbase\"},\"getCurrentBlockDifficulty()\":{\"notice\":\"Returns the block difficulty\"},\"getCurrentBlockGasLimit()\":{\"notice\":\"Returns the block gas limit\"},\"getCurrentBlockTimestamp()\":{\"notice\":\"Returns the block timestamp\"},\"getEthBalance(address)\":{\"notice\":\"Returns the (ETH) balance of a given address\"},\"getLastBlockHash()\":{\"notice\":\"Returns the block hash of the last block\"},\"tryAggregate(bool,(address,bytes)[])\":{\"notice\":\"Backwards-compatible with Multicall2Aggregate calls without requiring success\"},\"tryBlockAndAggregate(bool,(address,bytes)[])\":{\"notice\":\"Backwards-compatible with Multicall2Aggregate calls and allow failures using tryAggregate\"}},\"notice\":\"Aggregate results from multiple function calls but only allows a whitelisted set of msg.senders.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/external/PermissionedMulticall3.sol\":\"PermissionedMulticall3\"},\"debug\":{\"revertStrings\":\"strip\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"contracts/external/PermissionedMulticall3.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0; // Bumped version\\n\\n/**\\n * This is a simple fork of Multicall3 (the version found in this repo) that makes the contract Ownable\\n * and adds a whitelist of addresses that are allowed to call the contract's external functions.\\n **/\\n\\n/// @title PermissionedMulticall3\\n/// @notice Aggregate results from multiple function calls but only allows a whitelisted set of msg.senders.\\n/// @dev This contract is designed to be used as part of a permissioned system where this contract can be whitelisted\\n/// to call other contracts on behalf of the whitelisted senders. The benefit is that the whitelisted senders\\n/// can still batch call permissioned functions with unpermissioned functions by going through this contract.\\n/// @dev Multicall & Multicall2 backwards-compatible\\n/// @dev Aggregate methods are marked `payable` to save 24 gas per call\\n/// @author Michael Elliot \\n/// @author Joshua Levine \\n/// @author Nick Johnson \\n/// @author Andreas Bigger \\n/// @author Matt Solomon \\ncontract PermissionedMulticall3 {\\n struct Call {\\n address target;\\n bytes callData;\\n }\\n\\n struct Call3 {\\n address target;\\n bool allowFailure;\\n bytes callData;\\n }\\n\\n struct Call3Value {\\n address target;\\n bool allowFailure;\\n uint256 value;\\n bytes callData;\\n }\\n\\n struct Result {\\n bool success;\\n bytes returnData;\\n }\\n\\n /// @notice Backwards-compatible call aggregation with Multicall\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return returnData An array of bytes containing the responses\\n function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) {\\n blockNumber = block.number;\\n uint256 length = calls.length;\\n returnData = new bytes[](length);\\n Call calldata call;\\n for (uint256 i = 0; i < length; ) {\\n bool success;\\n call = calls[i];\\n (success, returnData[i]) = call.target.call(call.callData);\\n require(success, \\\"Multicall3: call failed\\\");\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls without requiring success\\n /// @param requireSuccess If true, require all calls to succeed\\n /// @param calls An array of Call structs\\n /// @return returnData An array of Result structs\\n function tryAggregate(bool requireSuccess, Call[] calldata calls)\\n public\\n payable\\n returns (Result[] memory returnData)\\n {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call calldata call;\\n for (uint256 i = 0; i < length; ) {\\n Result memory result = returnData[i];\\n call = calls[i];\\n (result.success, result.returnData) = call.target.call(call.callData);\\n if (requireSuccess) require(result.success, \\\"Multicall3: call failed\\\");\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)\\n public\\n payable\\n returns (\\n uint256 blockNumber,\\n bytes32 blockHash,\\n Result[] memory returnData\\n )\\n {\\n blockNumber = block.number;\\n blockHash = blockhash(block.number);\\n returnData = tryAggregate(requireSuccess, calls);\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function blockAndAggregate(Call[] calldata calls)\\n public\\n payable\\n returns (\\n uint256 blockNumber,\\n bytes32 blockHash,\\n Result[] memory returnData\\n )\\n {\\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\\n }\\n\\n /// @notice Aggregate calls, ensuring each returns success if required\\n /// @param calls An array of Call3 structs\\n /// @return returnData An array of Result structs\\n function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3 calldata calli;\\n for (uint256 i = 0; i < length; ) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n (result.success, result.returnData) = calli.target.call(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x64)\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Aggregate calls with a msg value\\n /// @notice Reverts if msg.value is less than the sum of the call values\\n /// @param calls An array of Call3Value structs\\n /// @return returnData An array of Result structs\\n function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 valAccumulator;\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3Value calldata calli;\\n for (uint256 i = 0; i < length; ) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n uint256 val = calli.value;\\n // Humanity will be a Type V Kardashev Civilization before this overflows - andreas\\n // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256\\n unchecked {\\n valAccumulator += val;\\n }\\n (result.success, result.returnData) = calli.target.call{ value: val }(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x84)\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n // Finally, make sure the msg.value = SUM(call[0...i].value)\\n require(msg.value == valAccumulator, \\\"Multicall3: value mismatch\\\");\\n }\\n\\n /// @notice Returns the block hash for the given block number\\n /// @param blockNumber The block number\\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\\n blockHash = blockhash(blockNumber);\\n }\\n\\n /// @notice Returns the block number\\n function getBlockNumber() public view returns (uint256 blockNumber) {\\n blockNumber = block.number;\\n }\\n\\n /// @notice Returns the block coinbase\\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\\n coinbase = block.coinbase;\\n }\\n\\n /// @notice Returns the block difficulty\\n function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {\\n difficulty = block.difficulty;\\n }\\n\\n /// @notice Returns the block gas limit\\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\\n gaslimit = block.gaslimit;\\n }\\n\\n /// @notice Returns the block timestamp\\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\\n timestamp = block.timestamp;\\n }\\n\\n /// @notice Returns the (ETH) balance of a given address\\n function getEthBalance(address addr) public view returns (uint256 balance) {\\n balance = addr.balance;\\n }\\n\\n /// @notice Returns the block hash of the last block\\n function getLastBlockHash() public view returns (bytes32 blockHash) {\\n unchecked {\\n blockHash = blockhash(block.number - 1);\\n }\\n }\\n\\n /// @notice Gets the base fee of the given block\\n /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain\\n function getBasefee() public view returns (uint256 basefee) {\\n basefee = block.basefee;\\n }\\n\\n /// @notice Returns the chain id\\n function getChainId() public view returns (uint256 chainid) {\\n chainid = block.chainid;\\n }\\n}\\n\",\"keccak256\":\"0x5f15d6c449e5a78591d3a645494d5f11304049abb1fb4a8ecd308f6f82b62c1a\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080806040523461001657610d5c908161001b8239f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c80630f28c97d14610114578063174dea711461010f578063252dba421461010a57806327e86d6e146101055780633408e47014610100578063399542e9146100fb5780633e64a696146100f657806342cbb15c146100f15780634d2301cc146100ec57806372425d9d146100e757806382ad56cb146100e257806386d516e8146100dd578063a8b0574e146100d8578063bce38bd7146100d3578063c3077fa9146100ce5763ee82ac5e146100c9575f80fd5b610981565b6108ec565b6108c9565b610891565b610859565b610773565b61073b565b6106f5565b61069f565b610667565b610643565b610598565b61053d565b610461565b6102cb565b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051428152f35b5f80fd5b9181601f8401121561014c5782359167ffffffffffffffff831161014c576020808501948460051b01011161014c57565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261014c576004359067ffffffffffffffff821161014c576101ca91600401610150565b9091565b91908251928382525f5b8481106102165750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b6020818301810151848301820152016101d8565b908082519081815260208091019281808460051b8301019501935f915b8483106102575750505050505090565b90919293949584806102a7837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528a5183604091805115158452015191818582015201906101ce565b9801930193019194939290610247565b9060206102c892818152019061022a565b90565b6102d436610181565b5f6102de82610a4b565b915f5b81811061030757610303846102f7853414610c10565b604051918291826102b7565b0390f35b6103118185610af6565b5161031d828488610b0f565b5f806040610350818501358099019861033586610b4f565b926103436060880188610b59565b9390915180948193610baa565b03925af19161035d610bb7565b90610372602094859384840152829015159052565b51910135171561038557506001016102e1565b7f08c379a0000000000000000000000000000000000000000000000000000000005f5260045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260845ffd5b906040820190825260206040602084015283518092526060830192602060608460051b8301019501935f915b8483106104155750505050505090565b9091929394958480610451837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa086600196030187528a516101ce565b9801930193019194939290610405565b61046a36610181565b9061047c61047783610a33565b6109ea565b918083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06104aa82610a33565b015f5b81811061052c5750505f5b8181106104ce57604051806103038643836103d9565b806105265f806104e16001958789610c17565b816104f96104ee83610b4f565b926020810190610b59565b919061050a60405180948193610baa565b03925af1610516610bb7565b6105208489610af6565b52610c10565b016104b8565b8060606020809388010152016104ad565b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c5760206040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4301408152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051468152f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261014c57600435801515810361014c57916024359067ffffffffffffffff821161014c576101ca91600401610150565b6102c8939260609282526020820152816040820152019061022a565b610303610658610652366105d0565b91610c97565b60405191829143404384610627565b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051488152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051438152f35b73ffffffffffffffffffffffffffffffffffffffff81160361014c57565b3461014c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020600435610732816106d7565b31604051908152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051448152f35b61077c36610181565b61078581610a4b565b905f5b81811061079d576040518061030385826102b7565b6107a78184610af6565b516107b3828487610c57565b5f806107be83610b4f565b6107d082604061034381880188610b59565b03925af1916107dd610bb7565b906107f2602094859384840152829015159052565b5191013517156108055750600101610788565b7f08c379a0000000000000000000000000000000000000000000000000000000005f5260045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260645ffd5b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051458152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051418152f35b6103036108d8610652366105d0565b60405191829160208352602083019061022a565b6108f536610181565b906108ff82610a4b565b905f5b83811061091b5760405180610303854380409084610627565b6109258184610af6565b51610931828685610c17565b5f80823561093e816106d7565b8161094e60209586810190610b59565b9190826040519384928337810182815203925af19061096b610bb7565b9083015215908115905261014c57600101610902565b3461014c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051600435408152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f604051930116820182811067ffffffffffffffff821117610a2e57604052565b6109bd565b67ffffffffffffffff8111610a2e5760051b60200190565b90610a5861047783610a33565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610a868294610a33565b015f5b818110610a9557505050565b604090815182810181811067ffffffffffffffff821117610a2e57602093525f815282606081830152828601015201610a89565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b8051821015610b0a5760209160051b010190565b610ac9565b9190811015610b0a5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818136030182121561014c570190565b356102c8816106d7565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561014c570180359067ffffffffffffffff821161014c5760200191813603831361014c57565b908092918237015f815290565b3d15610c0b573d9067ffffffffffffffff8211610a2e57610bff60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116016109ea565b9182523d5f602084013e565b606090565b1561014c57565b9190811015610b0a5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561014c570190565b9190811015610b0a5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18136030182121561014c570190565b929190610ca382610a4b565b935f5b838110610cb35750505050565b610cbd8187610af6565b5182610cca838787610c17565b5f808235610cd7816106d7565b81610ce760209586810190610b59565b9190826040519384928337810182815203925af190610d04610bb7565b90840152159182159052610d1c575b50600101610ca6565b61014c575f610d1356fea26469706673582212204a52938f5014dabd6b23a8f65d18231a1b28bd797868fd30d626fea52eecf38a64736f6c63430008170033", + "deployedBytecode": "0x60806040526004361015610011575f80fd5b5f3560e01c80630f28c97d14610114578063174dea711461010f578063252dba421461010a57806327e86d6e146101055780633408e47014610100578063399542e9146100fb5780633e64a696146100f657806342cbb15c146100f15780634d2301cc146100ec57806372425d9d146100e757806382ad56cb146100e257806386d516e8146100dd578063a8b0574e146100d8578063bce38bd7146100d3578063c3077fa9146100ce5763ee82ac5e146100c9575f80fd5b610981565b6108ec565b6108c9565b610891565b610859565b610773565b61073b565b6106f5565b61069f565b610667565b610643565b610598565b61053d565b610461565b6102cb565b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051428152f35b5f80fd5b9181601f8401121561014c5782359167ffffffffffffffff831161014c576020808501948460051b01011161014c57565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261014c576004359067ffffffffffffffff821161014c576101ca91600401610150565b9091565b91908251928382525f5b8481106102165750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b6020818301810151848301820152016101d8565b908082519081815260208091019281808460051b8301019501935f915b8483106102575750505050505090565b90919293949584806102a7837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528a5183604091805115158452015191818582015201906101ce565b9801930193019194939290610247565b9060206102c892818152019061022a565b90565b6102d436610181565b5f6102de82610a4b565b915f5b81811061030757610303846102f7853414610c10565b604051918291826102b7565b0390f35b6103118185610af6565b5161031d828488610b0f565b5f806040610350818501358099019861033586610b4f565b926103436060880188610b59565b9390915180948193610baa565b03925af19161035d610bb7565b90610372602094859384840152829015159052565b51910135171561038557506001016102e1565b7f08c379a0000000000000000000000000000000000000000000000000000000005f5260045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260845ffd5b906040820190825260206040602084015283518092526060830192602060608460051b8301019501935f915b8483106104155750505050505090565b9091929394958480610451837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa086600196030187528a516101ce565b9801930193019194939290610405565b61046a36610181565b9061047c61047783610a33565b6109ea565b918083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06104aa82610a33565b015f5b81811061052c5750505f5b8181106104ce57604051806103038643836103d9565b806105265f806104e16001958789610c17565b816104f96104ee83610b4f565b926020810190610b59565b919061050a60405180948193610baa565b03925af1610516610bb7565b6105208489610af6565b52610c10565b016104b8565b8060606020809388010152016104ad565b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c5760206040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4301408152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051468152f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261014c57600435801515810361014c57916024359067ffffffffffffffff821161014c576101ca91600401610150565b6102c8939260609282526020820152816040820152019061022a565b610303610658610652366105d0565b91610c97565b60405191829143404384610627565b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051488152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051438152f35b73ffffffffffffffffffffffffffffffffffffffff81160361014c57565b3461014c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020600435610732816106d7565b31604051908152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051448152f35b61077c36610181565b61078581610a4b565b905f5b81811061079d576040518061030385826102b7565b6107a78184610af6565b516107b3828487610c57565b5f806107be83610b4f565b6107d082604061034381880188610b59565b03925af1916107dd610bb7565b906107f2602094859384840152829015159052565b5191013517156108055750600101610788565b7f08c379a0000000000000000000000000000000000000000000000000000000005f5260045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260645ffd5b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051458152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051418152f35b6103036108d8610652366105d0565b60405191829160208352602083019061022a565b6108f536610181565b906108ff82610a4b565b905f5b83811061091b5760405180610303854380409084610627565b6109258184610af6565b51610931828685610c17565b5f80823561093e816106d7565b8161094e60209586810190610b59565b9190826040519384928337810182815203925af19061096b610bb7565b9083015215908115905261014c57600101610902565b3461014c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051600435408152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f604051930116820182811067ffffffffffffffff821117610a2e57604052565b6109bd565b67ffffffffffffffff8111610a2e5760051b60200190565b90610a5861047783610a33565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610a868294610a33565b015f5b818110610a9557505050565b604090815182810181811067ffffffffffffffff821117610a2e57602093525f815282606081830152828601015201610a89565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b8051821015610b0a5760209160051b010190565b610ac9565b9190811015610b0a5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818136030182121561014c570190565b356102c8816106d7565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561014c570180359067ffffffffffffffff821161014c5760200191813603831361014c57565b908092918237015f815290565b3d15610c0b573d9067ffffffffffffffff8211610a2e57610bff60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116016109ea565b9182523d5f602084013e565b606090565b1561014c57565b9190811015610b0a5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561014c570190565b9190811015610b0a5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18136030182121561014c570190565b929190610ca382610a4b565b935f5b838110610cb35750505050565b610cbd8187610af6565b5182610cca838787610c17565b5f808235610cd7816106d7565b81610ce760209586810190610b59565b9190826040519384928337810182815203925af190610d04610bb7565b90840152159182159052610d1c575b50600101610ca6565b61014c575f610d1356fea26469706673582212204a52938f5014dabd6b23a8f65d18231a1b28bd797868fd30d626fea52eecf38a64736f6c63430008170033", + "devdoc": { + "author": "Michael Elliot Joshua Levine Nick Johnson Andreas Bigger Matt Solomon ", + "details": "This contract is designed to be used as part of a permissioned system where this contract can be whitelisted to call other contracts on behalf of the whitelisted senders. The benefit is that the whitelisted senders can still batch call permissioned functions with unpermissioned functions by going through this contract.Multicall & Multicall2 backwards-compatibleAggregate methods are marked `payable` to save 24 gas per call", + "kind": "dev", + "methods": { + "aggregate((address,bytes)[])": { + "params": { + "calls": "An array of Call structs" + }, + "returns": { + "blockNumber": "The block number where the calls were executed", + "returnData": "An array of bytes containing the responses" + } + }, + "aggregate3((address,bool,bytes)[])": { + "params": { + "calls": "An array of Call3 structs" + }, + "returns": { + "returnData": "An array of Result structs" + } + }, + "aggregate3Value((address,bool,uint256,bytes)[])": { + "params": { + "calls": "An array of Call3Value structs" + }, + "returns": { + "returnData": "An array of Result structs" + } + }, + "blockAndAggregate((address,bytes)[])": { + "params": { + "calls": "An array of Call structs" + }, + "returns": { + "blockHash": "The hash of the block where the calls were executed", + "blockNumber": "The block number where the calls were executed", + "returnData": "An array of Result structs" + } + }, + "getBlockHash(uint256)": { + "params": { + "blockNumber": "The block number" + } + }, + "tryAggregate(bool,(address,bytes)[])": { + "params": { + "calls": "An array of Call structs", + "requireSuccess": "If true, require all calls to succeed" + }, + "returns": { + "returnData": "An array of Result structs" + } + }, + "tryBlockAndAggregate(bool,(address,bytes)[])": { + "params": { + "calls": "An array of Call structs" + }, + "returns": { + "blockHash": "The hash of the block where the calls were executed", + "blockNumber": "The block number where the calls were executed", + "returnData": "An array of Result structs" + } + } + }, + "title": "PermissionedMulticall3", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "aggregate((address,bytes)[])": { + "notice": "Backwards-compatible call aggregation with Multicall" + }, + "aggregate3((address,bool,bytes)[])": { + "notice": "Aggregate calls, ensuring each returns success if required" + }, + "aggregate3Value((address,bool,uint256,bytes)[])": { + "notice": "Aggregate calls with a msg valueReverts if msg.value is less than the sum of the call values" + }, + "blockAndAggregate((address,bytes)[])": { + "notice": "Backwards-compatible with Multicall2Aggregate calls and allow failures using tryAggregate" + }, + "getBasefee()": { + "notice": "Gets the base fee of the given blockCan revert if the BASEFEE opcode is not implemented by the given chain" + }, + "getBlockHash(uint256)": { + "notice": "Returns the block hash for the given block number" + }, + "getBlockNumber()": { + "notice": "Returns the block number" + }, + "getChainId()": { + "notice": "Returns the chain id" + }, + "getCurrentBlockCoinbase()": { + "notice": "Returns the block coinbase" + }, + "getCurrentBlockDifficulty()": { + "notice": "Returns the block difficulty" + }, + "getCurrentBlockGasLimit()": { + "notice": "Returns the block gas limit" + }, + "getCurrentBlockTimestamp()": { + "notice": "Returns the block timestamp" + }, + "getEthBalance(address)": { + "notice": "Returns the (ETH) balance of a given address" + }, + "getLastBlockHash()": { + "notice": "Returns the block hash of the last block" + }, + "tryAggregate(bool,(address,bytes)[])": { + "notice": "Backwards-compatible with Multicall2Aggregate calls without requiring success" + }, + "tryBlockAndAggregate(bool,(address,bytes)[])": { + "notice": "Backwards-compatible with Multicall2Aggregate calls and allow failures using tryAggregate" + } + }, + "notice": "Aggregate results from multiple function calls but only allows a whitelisted set of msg.senders.", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/bsc/solcInputs/8eea81dcd66c98bcacab463f809f2a48.json b/deployments/bsc/solcInputs/8eea81dcd66c98bcacab463f809f2a48.json new file mode 100644 index 000000000..2aebcdac9 --- /dev/null +++ b/deployments/bsc/solcInputs/8eea81dcd66c98bcacab463f809f2a48.json @@ -0,0 +1,37 @@ +{ + "language": "Solidity", + "sources": { + "contracts/external/PermissionedMulticall3.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0; // Bumped version\n\n/**\n * This is a simple fork of Multicall3 (the version found in this repo) that makes the contract Ownable\n * and adds a whitelist of addresses that are allowed to call the contract's external functions.\n **/\n\n/// @title PermissionedMulticall3\n/// @notice Aggregate results from multiple function calls but only allows a whitelisted set of msg.senders.\n/// @dev This contract is designed to be used as part of a permissioned system where this contract can be whitelisted\n/// to call other contracts on behalf of the whitelisted senders. The benefit is that the whitelisted senders\n/// can still batch call permissioned functions with unpermissioned functions by going through this contract.\n/// @dev Multicall & Multicall2 backwards-compatible\n/// @dev Aggregate methods are marked `payable` to save 24 gas per call\n/// @author Michael Elliot \n/// @author Joshua Levine \n/// @author Nick Johnson \n/// @author Andreas Bigger \n/// @author Matt Solomon \ncontract PermissionedMulticall3 {\n struct Call {\n address target;\n bytes callData;\n }\n\n struct Call3 {\n address target;\n bool allowFailure;\n bytes callData;\n }\n\n struct Call3Value {\n address target;\n bool allowFailure;\n uint256 value;\n bytes callData;\n }\n\n struct Result {\n bool success;\n bytes returnData;\n }\n\n /// @notice Backwards-compatible call aggregation with Multicall\n /// @param calls An array of Call structs\n /// @return blockNumber The block number where the calls were executed\n /// @return returnData An array of bytes containing the responses\n function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) {\n blockNumber = block.number;\n uint256 length = calls.length;\n returnData = new bytes[](length);\n Call calldata call;\n for (uint256 i = 0; i < length; ) {\n bool success;\n call = calls[i];\n (success, returnData[i]) = call.target.call(call.callData);\n require(success, \"Multicall3: call failed\");\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Backwards-compatible with Multicall2\n /// @notice Aggregate calls without requiring success\n /// @param requireSuccess If true, require all calls to succeed\n /// @param calls An array of Call structs\n /// @return returnData An array of Result structs\n function tryAggregate(bool requireSuccess, Call[] calldata calls)\n public\n payable\n returns (Result[] memory returnData)\n {\n uint256 length = calls.length;\n returnData = new Result[](length);\n Call calldata call;\n for (uint256 i = 0; i < length; ) {\n Result memory result = returnData[i];\n call = calls[i];\n (result.success, result.returnData) = call.target.call(call.callData);\n if (requireSuccess) require(result.success, \"Multicall3: call failed\");\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Backwards-compatible with Multicall2\n /// @notice Aggregate calls and allow failures using tryAggregate\n /// @param calls An array of Call structs\n /// @return blockNumber The block number where the calls were executed\n /// @return blockHash The hash of the block where the calls were executed\n /// @return returnData An array of Result structs\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)\n public\n payable\n returns (\n uint256 blockNumber,\n bytes32 blockHash,\n Result[] memory returnData\n )\n {\n blockNumber = block.number;\n blockHash = blockhash(block.number);\n returnData = tryAggregate(requireSuccess, calls);\n }\n\n /// @notice Backwards-compatible with Multicall2\n /// @notice Aggregate calls and allow failures using tryAggregate\n /// @param calls An array of Call structs\n /// @return blockNumber The block number where the calls were executed\n /// @return blockHash The hash of the block where the calls were executed\n /// @return returnData An array of Result structs\n function blockAndAggregate(Call[] calldata calls)\n public\n payable\n returns (\n uint256 blockNumber,\n bytes32 blockHash,\n Result[] memory returnData\n )\n {\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\n }\n\n /// @notice Aggregate calls, ensuring each returns success if required\n /// @param calls An array of Call3 structs\n /// @return returnData An array of Result structs\n function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) {\n uint256 length = calls.length;\n returnData = new Result[](length);\n Call3 calldata calli;\n for (uint256 i = 0; i < length; ) {\n Result memory result = returnData[i];\n calli = calls[i];\n (result.success, result.returnData) = calli.target.call(calli.callData);\n assembly {\n // Revert if the call fails and failure is not allowed\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\n // set \"Error(string)\" signature: bytes32(bytes4(keccak256(\"Error(string)\")))\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n // set data offset\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\n // set length of revert string\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\n // set revert string: bytes32(abi.encodePacked(\"Multicall3: call failed\"))\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\n revert(0x00, 0x64)\n }\n }\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Aggregate calls with a msg value\n /// @notice Reverts if msg.value is less than the sum of the call values\n /// @param calls An array of Call3Value structs\n /// @return returnData An array of Result structs\n function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) {\n uint256 valAccumulator;\n uint256 length = calls.length;\n returnData = new Result[](length);\n Call3Value calldata calli;\n for (uint256 i = 0; i < length; ) {\n Result memory result = returnData[i];\n calli = calls[i];\n uint256 val = calli.value;\n // Humanity will be a Type V Kardashev Civilization before this overflows - andreas\n // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256\n unchecked {\n valAccumulator += val;\n }\n (result.success, result.returnData) = calli.target.call{ value: val }(calli.callData);\n assembly {\n // Revert if the call fails and failure is not allowed\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\n // set \"Error(string)\" signature: bytes32(bytes4(keccak256(\"Error(string)\")))\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n // set data offset\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\n // set length of revert string\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\n // set revert string: bytes32(abi.encodePacked(\"Multicall3: call failed\"))\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\n revert(0x00, 0x84)\n }\n }\n unchecked {\n ++i;\n }\n }\n // Finally, make sure the msg.value = SUM(call[0...i].value)\n require(msg.value == valAccumulator, \"Multicall3: value mismatch\");\n }\n\n /// @notice Returns the block hash for the given block number\n /// @param blockNumber The block number\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\n blockHash = blockhash(blockNumber);\n }\n\n /// @notice Returns the block number\n function getBlockNumber() public view returns (uint256 blockNumber) {\n blockNumber = block.number;\n }\n\n /// @notice Returns the block coinbase\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\n coinbase = block.coinbase;\n }\n\n /// @notice Returns the block difficulty\n function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {\n difficulty = block.difficulty;\n }\n\n /// @notice Returns the block gas limit\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\n gaslimit = block.gaslimit;\n }\n\n /// @notice Returns the block timestamp\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\n timestamp = block.timestamp;\n }\n\n /// @notice Returns the (ETH) balance of a given address\n function getEthBalance(address addr) public view returns (uint256 balance) {\n balance = addr.balance;\n }\n\n /// @notice Returns the block hash of the last block\n function getLastBlockHash() public view returns (bytes32 blockHash) {\n unchecked {\n blockHash = blockhash(block.number - 1);\n }\n }\n\n /// @notice Gets the base fee of the given block\n /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain\n function getBasefee() public view returns (uint256 basefee) {\n basefee = block.basefee;\n }\n\n /// @notice Returns the chain id\n function getChainId() public view returns (uint256 chainid) {\n chainid = block.chainid;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "viaIR": true, + "debug": { + "revertStrings": "strip" + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} From f7f7f2fa6d18d2ebc97b89291397d61328c28dd1 Mon Sep 17 00:00:00 2001 From: nicholaspai Date: Mon, 5 May 2025 13:52:16 -0400 Subject: [PATCH 3/3] Redeploy with ownership logic --- contracts/external/PermissionedMulticall3.sol | 38 +++- deployments/bsc/PermissionedMulticall3.json | 185 ++++++++++++++++-- .../8cf77b572b3c86de2e87d5cc0dc68812.json | 43 ++++ 3 files changed, 245 insertions(+), 21 deletions(-) create mode 100644 deployments/bsc/solcInputs/8cf77b572b3c86de2e87d5cc0dc68812.json diff --git a/contracts/external/PermissionedMulticall3.sol b/contracts/external/PermissionedMulticall3.sol index 73c95d135..e8d4ca857 100644 --- a/contracts/external/PermissionedMulticall3.sol +++ b/contracts/external/PermissionedMulticall3.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // Bumped version +import "@openzeppelin/contracts/access/Ownable.sol"; + /** * This is a simple fork of Multicall3 (the version found in this repo) that makes the contract Ownable * and adds a whitelist of addresses that are allowed to call the contract's external functions. @@ -18,7 +20,10 @@ pragma solidity ^0.8.0; // Bumped version /// @author Nick Johnson /// @author Andreas Bigger /// @author Matt Solomon -contract PermissionedMulticall3 { +contract PermissionedMulticall3 is Ownable { + /// @notice Callers who can call state changing public functions. + mapping(address => bool) public whitelistedSenders; + struct Call { address target; bytes callData; @@ -42,11 +47,28 @@ contract PermissionedMulticall3 { bytes returnData; } + modifier onlyWhitelisted() { + require(whitelistedSenders[msg.sender], "sender not whitelisted"); + _; + } + + function whitelist(address[] calldata senders, bool[] calldata value) external onlyOwner { + require(senders.length == value.length, "senders and values length mismatch"); + for (uint256 i = 0; i < senders.length; i++) { + whitelistedSenders[senders[i]] = value[i]; + } + } + /// @notice Backwards-compatible call aggregation with Multicall /// @param calls An array of Call structs /// @return blockNumber The block number where the calls were executed /// @return returnData An array of bytes containing the responses - function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) { + function aggregate(Call[] calldata calls) + public + payable + onlyWhitelisted + returns (uint256 blockNumber, bytes[] memory returnData) + { blockNumber = block.number; uint256 length = calls.length; returnData = new bytes[](length); @@ -70,6 +92,7 @@ contract PermissionedMulticall3 { function tryAggregate(bool requireSuccess, Call[] calldata calls) public payable + onlyWhitelisted returns (Result[] memory returnData) { uint256 length = calls.length; @@ -95,6 +118,7 @@ contract PermissionedMulticall3 { function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) public payable + onlyWhitelisted returns ( uint256 blockNumber, bytes32 blockHash, @@ -115,6 +139,7 @@ contract PermissionedMulticall3 { function blockAndAggregate(Call[] calldata calls) public payable + onlyWhitelisted returns ( uint256 blockNumber, bytes32 blockHash, @@ -127,7 +152,7 @@ contract PermissionedMulticall3 { /// @notice Aggregate calls, ensuring each returns success if required /// @param calls An array of Call3 structs /// @return returnData An array of Result structs - function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) { + function aggregate3(Call3[] calldata calls) public payable onlyWhitelisted returns (Result[] memory returnData) { uint256 length = calls.length; returnData = new Result[](length); Call3 calldata calli; @@ -160,7 +185,12 @@ contract PermissionedMulticall3 { /// @notice Reverts if msg.value is less than the sum of the call values /// @param calls An array of Call3Value structs /// @return returnData An array of Result structs - function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) { + function aggregate3Value(Call3Value[] calldata calls) + public + payable + onlyWhitelisted + returns (Result[] memory returnData) + { uint256 valAccumulator; uint256 length = calls.length; returnData = new Result[](length); diff --git a/deployments/bsc/PermissionedMulticall3.json b/deployments/bsc/PermissionedMulticall3.json index 5349b5f1c..cdde64718 100644 --- a/deployments/bsc/PermissionedMulticall3.json +++ b/deployments/bsc/PermissionedMulticall3.json @@ -1,6 +1,25 @@ { - "address": "0x38015ddB8b34c84934Cff058F571349Cc7d4139d", + "address": "0x9367CC85B16932b19ee160A7AA2B251C8606d5b4", "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, { "inputs": [ { @@ -333,6 +352,39 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -438,30 +490,82 @@ ], "stateMutability": "payable", "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "senders", + "type": "address[]" + }, + { + "internalType": "bool[]", + "name": "value", + "type": "bool[]" + } + ], + "name": "whitelist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "whitelistedSenders", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" } ], - "transactionHash": "0x541a58a25a3184b1bc7606bafec5f50445ad7a82d40a9f20f10a6f2a599c0b03", + "transactionHash": "0x4e70981b2db65cd88e330a6604460cf59d9918c667bc41a9e2fa826b2adba911", "receipt": { "to": null, "from": "0x9A8f92a830A5cB89a3816e3D267CB7791c16b04D", - "contractAddress": "0x38015ddB8b34c84934Cff058F571349Cc7d4139d", - "transactionIndex": 20, - "gasUsed": "791327", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x5ef391a594a50a49b61faa6bb168b9471bfce2198e9742f66ab41c69d60b2dd3", - "transactionHash": "0x541a58a25a3184b1bc7606bafec5f50445ad7a82d40a9f20f10a6f2a599c0b03", - "logs": [], - "blockNumber": 49092597, - "cumulativeGasUsed": "4316908", + "contractAddress": "0x9367CC85B16932b19ee160A7AA2B251C8606d5b4", + "transactionIndex": 46, + "gasUsed": "1045599", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000040000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000800000000000000000000000000000000000000000000020010001000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xe2e4e5058709fc8fccb086b354b4b86d717c9d5025838fc7a347c5020363964a", + "transactionHash": "0x4e70981b2db65cd88e330a6604460cf59d9918c667bc41a9e2fa826b2adba911", + "logs": [ + { + "transactionIndex": 46, + "blockNumber": 49149586, + "transactionHash": "0x4e70981b2db65cd88e330a6604460cf59d9918c667bc41a9e2fa826b2adba911", + "address": "0x9367CC85B16932b19ee160A7AA2B251C8606d5b4", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000009a8f92a830a5cb89a3816e3d267cb7791c16b04d" + ], + "data": "0x", + "logIndex": 164, + "blockHash": "0xe2e4e5058709fc8fccb086b354b4b86d717c9d5025838fc7a347c5020363964a" + } + ], + "blockNumber": 49149586, + "cumulativeGasUsed": "6610930", "status": 1, "byzantium": true }, "args": [], "numDeployments": 1, - "solcInputHash": "8eea81dcd66c98bcacab463f809f2a48", - "metadata": "{\"compiler\":{\"version\":\"0.8.23+commit.f704f362\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"returnData\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call3[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call3Value[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3Value\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"blockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBasefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"basefee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"getBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainid\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockCoinbase\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"coinbase\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockDifficulty\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"difficulty\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockGasLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gaslimit\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getEthBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryAggregate\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryBlockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Michael Elliot Joshua Levine Nick Johnson Andreas Bigger Matt Solomon \",\"details\":\"This contract is designed to be used as part of a permissioned system where this contract can be whitelisted to call other contracts on behalf of the whitelisted senders. The benefit is that the whitelisted senders can still batch call permissioned functions with unpermissioned functions by going through this contract.Multicall & Multicall2 backwards-compatibleAggregate methods are marked `payable` to save 24 gas per call\",\"kind\":\"dev\",\"methods\":{\"aggregate((address,bytes)[])\":{\"params\":{\"calls\":\"An array of Call structs\"},\"returns\":{\"blockNumber\":\"The block number where the calls were executed\",\"returnData\":\"An array of bytes containing the responses\"}},\"aggregate3((address,bool,bytes)[])\":{\"params\":{\"calls\":\"An array of Call3 structs\"},\"returns\":{\"returnData\":\"An array of Result structs\"}},\"aggregate3Value((address,bool,uint256,bytes)[])\":{\"params\":{\"calls\":\"An array of Call3Value structs\"},\"returns\":{\"returnData\":\"An array of Result structs\"}},\"blockAndAggregate((address,bytes)[])\":{\"params\":{\"calls\":\"An array of Call structs\"},\"returns\":{\"blockHash\":\"The hash of the block where the calls were executed\",\"blockNumber\":\"The block number where the calls were executed\",\"returnData\":\"An array of Result structs\"}},\"getBlockHash(uint256)\":{\"params\":{\"blockNumber\":\"The block number\"}},\"tryAggregate(bool,(address,bytes)[])\":{\"params\":{\"calls\":\"An array of Call structs\",\"requireSuccess\":\"If true, require all calls to succeed\"},\"returns\":{\"returnData\":\"An array of Result structs\"}},\"tryBlockAndAggregate(bool,(address,bytes)[])\":{\"params\":{\"calls\":\"An array of Call structs\"},\"returns\":{\"blockHash\":\"The hash of the block where the calls were executed\",\"blockNumber\":\"The block number where the calls were executed\",\"returnData\":\"An array of Result structs\"}}},\"title\":\"PermissionedMulticall3\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"aggregate((address,bytes)[])\":{\"notice\":\"Backwards-compatible call aggregation with Multicall\"},\"aggregate3((address,bool,bytes)[])\":{\"notice\":\"Aggregate calls, ensuring each returns success if required\"},\"aggregate3Value((address,bool,uint256,bytes)[])\":{\"notice\":\"Aggregate calls with a msg valueReverts if msg.value is less than the sum of the call values\"},\"blockAndAggregate((address,bytes)[])\":{\"notice\":\"Backwards-compatible with Multicall2Aggregate calls and allow failures using tryAggregate\"},\"getBasefee()\":{\"notice\":\"Gets the base fee of the given blockCan revert if the BASEFEE opcode is not implemented by the given chain\"},\"getBlockHash(uint256)\":{\"notice\":\"Returns the block hash for the given block number\"},\"getBlockNumber()\":{\"notice\":\"Returns the block number\"},\"getChainId()\":{\"notice\":\"Returns the chain id\"},\"getCurrentBlockCoinbase()\":{\"notice\":\"Returns the block coinbase\"},\"getCurrentBlockDifficulty()\":{\"notice\":\"Returns the block difficulty\"},\"getCurrentBlockGasLimit()\":{\"notice\":\"Returns the block gas limit\"},\"getCurrentBlockTimestamp()\":{\"notice\":\"Returns the block timestamp\"},\"getEthBalance(address)\":{\"notice\":\"Returns the (ETH) balance of a given address\"},\"getLastBlockHash()\":{\"notice\":\"Returns the block hash of the last block\"},\"tryAggregate(bool,(address,bytes)[])\":{\"notice\":\"Backwards-compatible with Multicall2Aggregate calls without requiring success\"},\"tryBlockAndAggregate(bool,(address,bytes)[])\":{\"notice\":\"Backwards-compatible with Multicall2Aggregate calls and allow failures using tryAggregate\"}},\"notice\":\"Aggregate results from multiple function calls but only allows a whitelisted set of msg.senders.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/external/PermissionedMulticall3.sol\":\"PermissionedMulticall3\"},\"debug\":{\"revertStrings\":\"strip\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"contracts/external/PermissionedMulticall3.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0; // Bumped version\\n\\n/**\\n * This is a simple fork of Multicall3 (the version found in this repo) that makes the contract Ownable\\n * and adds a whitelist of addresses that are allowed to call the contract's external functions.\\n **/\\n\\n/// @title PermissionedMulticall3\\n/// @notice Aggregate results from multiple function calls but only allows a whitelisted set of msg.senders.\\n/// @dev This contract is designed to be used as part of a permissioned system where this contract can be whitelisted\\n/// to call other contracts on behalf of the whitelisted senders. The benefit is that the whitelisted senders\\n/// can still batch call permissioned functions with unpermissioned functions by going through this contract.\\n/// @dev Multicall & Multicall2 backwards-compatible\\n/// @dev Aggregate methods are marked `payable` to save 24 gas per call\\n/// @author Michael Elliot \\n/// @author Joshua Levine \\n/// @author Nick Johnson \\n/// @author Andreas Bigger \\n/// @author Matt Solomon \\ncontract PermissionedMulticall3 {\\n struct Call {\\n address target;\\n bytes callData;\\n }\\n\\n struct Call3 {\\n address target;\\n bool allowFailure;\\n bytes callData;\\n }\\n\\n struct Call3Value {\\n address target;\\n bool allowFailure;\\n uint256 value;\\n bytes callData;\\n }\\n\\n struct Result {\\n bool success;\\n bytes returnData;\\n }\\n\\n /// @notice Backwards-compatible call aggregation with Multicall\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return returnData An array of bytes containing the responses\\n function aggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes[] memory returnData) {\\n blockNumber = block.number;\\n uint256 length = calls.length;\\n returnData = new bytes[](length);\\n Call calldata call;\\n for (uint256 i = 0; i < length; ) {\\n bool success;\\n call = calls[i];\\n (success, returnData[i]) = call.target.call(call.callData);\\n require(success, \\\"Multicall3: call failed\\\");\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls without requiring success\\n /// @param requireSuccess If true, require all calls to succeed\\n /// @param calls An array of Call structs\\n /// @return returnData An array of Result structs\\n function tryAggregate(bool requireSuccess, Call[] calldata calls)\\n public\\n payable\\n returns (Result[] memory returnData)\\n {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call calldata call;\\n for (uint256 i = 0; i < length; ) {\\n Result memory result = returnData[i];\\n call = calls[i];\\n (result.success, result.returnData) = call.target.call(call.callData);\\n if (requireSuccess) require(result.success, \\\"Multicall3: call failed\\\");\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)\\n public\\n payable\\n returns (\\n uint256 blockNumber,\\n bytes32 blockHash,\\n Result[] memory returnData\\n )\\n {\\n blockNumber = block.number;\\n blockHash = blockhash(block.number);\\n returnData = tryAggregate(requireSuccess, calls);\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function blockAndAggregate(Call[] calldata calls)\\n public\\n payable\\n returns (\\n uint256 blockNumber,\\n bytes32 blockHash,\\n Result[] memory returnData\\n )\\n {\\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\\n }\\n\\n /// @notice Aggregate calls, ensuring each returns success if required\\n /// @param calls An array of Call3 structs\\n /// @return returnData An array of Result structs\\n function aggregate3(Call3[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3 calldata calli;\\n for (uint256 i = 0; i < length; ) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n (result.success, result.returnData) = calli.target.call(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x64)\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Aggregate calls with a msg value\\n /// @notice Reverts if msg.value is less than the sum of the call values\\n /// @param calls An array of Call3Value structs\\n /// @return returnData An array of Result structs\\n function aggregate3Value(Call3Value[] calldata calls) public payable returns (Result[] memory returnData) {\\n uint256 valAccumulator;\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3Value calldata calli;\\n for (uint256 i = 0; i < length; ) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n uint256 val = calli.value;\\n // Humanity will be a Type V Kardashev Civilization before this overflows - andreas\\n // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256\\n unchecked {\\n valAccumulator += val;\\n }\\n (result.success, result.returnData) = calli.target.call{ value: val }(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x84)\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n // Finally, make sure the msg.value = SUM(call[0...i].value)\\n require(msg.value == valAccumulator, \\\"Multicall3: value mismatch\\\");\\n }\\n\\n /// @notice Returns the block hash for the given block number\\n /// @param blockNumber The block number\\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\\n blockHash = blockhash(blockNumber);\\n }\\n\\n /// @notice Returns the block number\\n function getBlockNumber() public view returns (uint256 blockNumber) {\\n blockNumber = block.number;\\n }\\n\\n /// @notice Returns the block coinbase\\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\\n coinbase = block.coinbase;\\n }\\n\\n /// @notice Returns the block difficulty\\n function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {\\n difficulty = block.difficulty;\\n }\\n\\n /// @notice Returns the block gas limit\\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\\n gaslimit = block.gaslimit;\\n }\\n\\n /// @notice Returns the block timestamp\\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\\n timestamp = block.timestamp;\\n }\\n\\n /// @notice Returns the (ETH) balance of a given address\\n function getEthBalance(address addr) public view returns (uint256 balance) {\\n balance = addr.balance;\\n }\\n\\n /// @notice Returns the block hash of the last block\\n function getLastBlockHash() public view returns (bytes32 blockHash) {\\n unchecked {\\n blockHash = blockhash(block.number - 1);\\n }\\n }\\n\\n /// @notice Gets the base fee of the given block\\n /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain\\n function getBasefee() public view returns (uint256 basefee) {\\n basefee = block.basefee;\\n }\\n\\n /// @notice Returns the chain id\\n function getChainId() public view returns (uint256 chainid) {\\n chainid = block.chainid;\\n }\\n}\\n\",\"keccak256\":\"0x5f15d6c449e5a78591d3a645494d5f11304049abb1fb4a8ecd308f6f82b62c1a\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x6080806040523461001657610d5c908161001b8239f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c80630f28c97d14610114578063174dea711461010f578063252dba421461010a57806327e86d6e146101055780633408e47014610100578063399542e9146100fb5780633e64a696146100f657806342cbb15c146100f15780634d2301cc146100ec57806372425d9d146100e757806382ad56cb146100e257806386d516e8146100dd578063a8b0574e146100d8578063bce38bd7146100d3578063c3077fa9146100ce5763ee82ac5e146100c9575f80fd5b610981565b6108ec565b6108c9565b610891565b610859565b610773565b61073b565b6106f5565b61069f565b610667565b610643565b610598565b61053d565b610461565b6102cb565b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051428152f35b5f80fd5b9181601f8401121561014c5782359167ffffffffffffffff831161014c576020808501948460051b01011161014c57565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261014c576004359067ffffffffffffffff821161014c576101ca91600401610150565b9091565b91908251928382525f5b8481106102165750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b6020818301810151848301820152016101d8565b908082519081815260208091019281808460051b8301019501935f915b8483106102575750505050505090565b90919293949584806102a7837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528a5183604091805115158452015191818582015201906101ce565b9801930193019194939290610247565b9060206102c892818152019061022a565b90565b6102d436610181565b5f6102de82610a4b565b915f5b81811061030757610303846102f7853414610c10565b604051918291826102b7565b0390f35b6103118185610af6565b5161031d828488610b0f565b5f806040610350818501358099019861033586610b4f565b926103436060880188610b59565b9390915180948193610baa565b03925af19161035d610bb7565b90610372602094859384840152829015159052565b51910135171561038557506001016102e1565b7f08c379a0000000000000000000000000000000000000000000000000000000005f5260045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260845ffd5b906040820190825260206040602084015283518092526060830192602060608460051b8301019501935f915b8483106104155750505050505090565b9091929394958480610451837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa086600196030187528a516101ce565b9801930193019194939290610405565b61046a36610181565b9061047c61047783610a33565b6109ea565b918083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06104aa82610a33565b015f5b81811061052c5750505f5b8181106104ce57604051806103038643836103d9565b806105265f806104e16001958789610c17565b816104f96104ee83610b4f565b926020810190610b59565b919061050a60405180948193610baa565b03925af1610516610bb7565b6105208489610af6565b52610c10565b016104b8565b8060606020809388010152016104ad565b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c5760206040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4301408152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051468152f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261014c57600435801515810361014c57916024359067ffffffffffffffff821161014c576101ca91600401610150565b6102c8939260609282526020820152816040820152019061022a565b610303610658610652366105d0565b91610c97565b60405191829143404384610627565b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051488152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051438152f35b73ffffffffffffffffffffffffffffffffffffffff81160361014c57565b3461014c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020600435610732816106d7565b31604051908152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051448152f35b61077c36610181565b61078581610a4b565b905f5b81811061079d576040518061030385826102b7565b6107a78184610af6565b516107b3828487610c57565b5f806107be83610b4f565b6107d082604061034381880188610b59565b03925af1916107dd610bb7565b906107f2602094859384840152829015159052565b5191013517156108055750600101610788565b7f08c379a0000000000000000000000000000000000000000000000000000000005f5260045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260645ffd5b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051458152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051418152f35b6103036108d8610652366105d0565b60405191829160208352602083019061022a565b6108f536610181565b906108ff82610a4b565b905f5b83811061091b5760405180610303854380409084610627565b6109258184610af6565b51610931828685610c17565b5f80823561093e816106d7565b8161094e60209586810190610b59565b9190826040519384928337810182815203925af19061096b610bb7565b9083015215908115905261014c57600101610902565b3461014c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051600435408152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f604051930116820182811067ffffffffffffffff821117610a2e57604052565b6109bd565b67ffffffffffffffff8111610a2e5760051b60200190565b90610a5861047783610a33565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610a868294610a33565b015f5b818110610a9557505050565b604090815182810181811067ffffffffffffffff821117610a2e57602093525f815282606081830152828601015201610a89565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b8051821015610b0a5760209160051b010190565b610ac9565b9190811015610b0a5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818136030182121561014c570190565b356102c8816106d7565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561014c570180359067ffffffffffffffff821161014c5760200191813603831361014c57565b908092918237015f815290565b3d15610c0b573d9067ffffffffffffffff8211610a2e57610bff60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116016109ea565b9182523d5f602084013e565b606090565b1561014c57565b9190811015610b0a5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561014c570190565b9190811015610b0a5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18136030182121561014c570190565b929190610ca382610a4b565b935f5b838110610cb35750505050565b610cbd8187610af6565b5182610cca838787610c17565b5f808235610cd7816106d7565b81610ce760209586810190610b59565b9190826040519384928337810182815203925af190610d04610bb7565b90840152159182159052610d1c575b50600101610ca6565b61014c575f610d1356fea26469706673582212204a52938f5014dabd6b23a8f65d18231a1b28bd797868fd30d626fea52eecf38a64736f6c63430008170033", - "deployedBytecode": "0x60806040526004361015610011575f80fd5b5f3560e01c80630f28c97d14610114578063174dea711461010f578063252dba421461010a57806327e86d6e146101055780633408e47014610100578063399542e9146100fb5780633e64a696146100f657806342cbb15c146100f15780634d2301cc146100ec57806372425d9d146100e757806382ad56cb146100e257806386d516e8146100dd578063a8b0574e146100d8578063bce38bd7146100d3578063c3077fa9146100ce5763ee82ac5e146100c9575f80fd5b610981565b6108ec565b6108c9565b610891565b610859565b610773565b61073b565b6106f5565b61069f565b610667565b610643565b610598565b61053d565b610461565b6102cb565b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051428152f35b5f80fd5b9181601f8401121561014c5782359167ffffffffffffffff831161014c576020808501948460051b01011161014c57565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261014c576004359067ffffffffffffffff821161014c576101ca91600401610150565b9091565b91908251928382525f5b8481106102165750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b6020818301810151848301820152016101d8565b908082519081815260208091019281808460051b8301019501935f915b8483106102575750505050505090565b90919293949584806102a7837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528a5183604091805115158452015191818582015201906101ce565b9801930193019194939290610247565b9060206102c892818152019061022a565b90565b6102d436610181565b5f6102de82610a4b565b915f5b81811061030757610303846102f7853414610c10565b604051918291826102b7565b0390f35b6103118185610af6565b5161031d828488610b0f565b5f806040610350818501358099019861033586610b4f565b926103436060880188610b59565b9390915180948193610baa565b03925af19161035d610bb7565b90610372602094859384840152829015159052565b51910135171561038557506001016102e1565b7f08c379a0000000000000000000000000000000000000000000000000000000005f5260045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260845ffd5b906040820190825260206040602084015283518092526060830192602060608460051b8301019501935f915b8483106104155750505050505090565b9091929394958480610451837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa086600196030187528a516101ce565b9801930193019194939290610405565b61046a36610181565b9061047c61047783610a33565b6109ea565b918083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06104aa82610a33565b015f5b81811061052c5750505f5b8181106104ce57604051806103038643836103d9565b806105265f806104e16001958789610c17565b816104f96104ee83610b4f565b926020810190610b59565b919061050a60405180948193610baa565b03925af1610516610bb7565b6105208489610af6565b52610c10565b016104b8565b8060606020809388010152016104ad565b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c5760206040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4301408152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051468152f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261014c57600435801515810361014c57916024359067ffffffffffffffff821161014c576101ca91600401610150565b6102c8939260609282526020820152816040820152019061022a565b610303610658610652366105d0565b91610c97565b60405191829143404384610627565b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051488152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051438152f35b73ffffffffffffffffffffffffffffffffffffffff81160361014c57565b3461014c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020600435610732816106d7565b31604051908152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051448152f35b61077c36610181565b61078581610a4b565b905f5b81811061079d576040518061030385826102b7565b6107a78184610af6565b516107b3828487610c57565b5f806107be83610b4f565b6107d082604061034381880188610b59565b03925af1916107dd610bb7565b906107f2602094859384840152829015159052565b5191013517156108055750600101610788565b7f08c379a0000000000000000000000000000000000000000000000000000000005f5260045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260645ffd5b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051458152f35b3461014c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051418152f35b6103036108d8610652366105d0565b60405191829160208352602083019061022a565b6108f536610181565b906108ff82610a4b565b905f5b83811061091b5760405180610303854380409084610627565b6109258184610af6565b51610931828685610c17565b5f80823561093e816106d7565b8161094e60209586810190610b59565b9190826040519384928337810182815203925af19061096b610bb7565b9083015215908115905261014c57600101610902565b3461014c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261014c576020604051600435408152f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f604051930116820182811067ffffffffffffffff821117610a2e57604052565b6109bd565b67ffffffffffffffff8111610a2e5760051b60200190565b90610a5861047783610a33565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610a868294610a33565b015f5b818110610a9557505050565b604090815182810181811067ffffffffffffffff821117610a2e57602093525f815282606081830152828601015201610a89565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b8051821015610b0a5760209160051b010190565b610ac9565b9190811015610b0a5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818136030182121561014c570190565b356102c8816106d7565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561014c570180359067ffffffffffffffff821161014c5760200191813603831361014c57565b908092918237015f815290565b3d15610c0b573d9067ffffffffffffffff8211610a2e57610bff60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116016109ea565b9182523d5f602084013e565b606090565b1561014c57565b9190811015610b0a5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561014c570190565b9190811015610b0a5760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18136030182121561014c570190565b929190610ca382610a4b565b935f5b838110610cb35750505050565b610cbd8187610af6565b5182610cca838787610c17565b5f808235610cd7816106d7565b81610ce760209586810190610b59565b9190826040519384928337810182815203925af190610d04610bb7565b90840152159182159052610d1c575b50600101610ca6565b61014c575f610d1356fea26469706673582212204a52938f5014dabd6b23a8f65d18231a1b28bd797868fd30d626fea52eecf38a64736f6c63430008170033", + "solcInputHash": "8cf77b572b3c86de2e87d5cc0dc68812", + "metadata": "{\"compiler\":{\"version\":\"0.8.23+commit.f704f362\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"returnData\",\"type\":\"bytes[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call3[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowFailure\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call3Value[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"aggregate3Value\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"blockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBasefee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"basefee\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"getBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"chainid\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockCoinbase\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"coinbase\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockDifficulty\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"difficulty\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockGasLimit\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"gaslimit\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentBlockTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"getEthBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLastBlockHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryAggregate\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"requireSuccess\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Call[]\",\"name\":\"calls\",\"type\":\"tuple[]\"}],\"name\":\"tryBlockAndAggregate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct PermissionedMulticall3.Result[]\",\"name\":\"returnData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"},{\"internalType\":\"bool[]\",\"name\":\"value\",\"type\":\"bool[]\"}],\"name\":\"whitelist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"whitelistedSenders\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Michael Elliot Joshua Levine Nick Johnson Andreas Bigger Matt Solomon \",\"details\":\"This contract is designed to be used as part of a permissioned system where this contract can be whitelisted to call other contracts on behalf of the whitelisted senders. The benefit is that the whitelisted senders can still batch call permissioned functions with unpermissioned functions by going through this contract.Multicall & Multicall2 backwards-compatibleAggregate methods are marked `payable` to save 24 gas per call\",\"kind\":\"dev\",\"methods\":{\"aggregate((address,bytes)[])\":{\"params\":{\"calls\":\"An array of Call structs\"},\"returns\":{\"blockNumber\":\"The block number where the calls were executed\",\"returnData\":\"An array of bytes containing the responses\"}},\"aggregate3((address,bool,bytes)[])\":{\"params\":{\"calls\":\"An array of Call3 structs\"},\"returns\":{\"returnData\":\"An array of Result structs\"}},\"aggregate3Value((address,bool,uint256,bytes)[])\":{\"params\":{\"calls\":\"An array of Call3Value structs\"},\"returns\":{\"returnData\":\"An array of Result structs\"}},\"blockAndAggregate((address,bytes)[])\":{\"params\":{\"calls\":\"An array of Call structs\"},\"returns\":{\"blockHash\":\"The hash of the block where the calls were executed\",\"blockNumber\":\"The block number where the calls were executed\",\"returnData\":\"An array of Result structs\"}},\"getBlockHash(uint256)\":{\"params\":{\"blockNumber\":\"The block number\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"tryAggregate(bool,(address,bytes)[])\":{\"params\":{\"calls\":\"An array of Call structs\",\"requireSuccess\":\"If true, require all calls to succeed\"},\"returns\":{\"returnData\":\"An array of Result structs\"}},\"tryBlockAndAggregate(bool,(address,bytes)[])\":{\"params\":{\"calls\":\"An array of Call structs\"},\"returns\":{\"blockHash\":\"The hash of the block where the calls were executed\",\"blockNumber\":\"The block number where the calls were executed\",\"returnData\":\"An array of Result structs\"}}},\"title\":\"PermissionedMulticall3\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"aggregate((address,bytes)[])\":{\"notice\":\"Backwards-compatible call aggregation with Multicall\"},\"aggregate3((address,bool,bytes)[])\":{\"notice\":\"Aggregate calls, ensuring each returns success if required\"},\"aggregate3Value((address,bool,uint256,bytes)[])\":{\"notice\":\"Aggregate calls with a msg valueReverts if msg.value is less than the sum of the call values\"},\"blockAndAggregate((address,bytes)[])\":{\"notice\":\"Backwards-compatible with Multicall2Aggregate calls and allow failures using tryAggregate\"},\"getBasefee()\":{\"notice\":\"Gets the base fee of the given blockCan revert if the BASEFEE opcode is not implemented by the given chain\"},\"getBlockHash(uint256)\":{\"notice\":\"Returns the block hash for the given block number\"},\"getBlockNumber()\":{\"notice\":\"Returns the block number\"},\"getChainId()\":{\"notice\":\"Returns the chain id\"},\"getCurrentBlockCoinbase()\":{\"notice\":\"Returns the block coinbase\"},\"getCurrentBlockDifficulty()\":{\"notice\":\"Returns the block difficulty\"},\"getCurrentBlockGasLimit()\":{\"notice\":\"Returns the block gas limit\"},\"getCurrentBlockTimestamp()\":{\"notice\":\"Returns the block timestamp\"},\"getEthBalance(address)\":{\"notice\":\"Returns the (ETH) balance of a given address\"},\"getLastBlockHash()\":{\"notice\":\"Returns the block hash of the last block\"},\"tryAggregate(bool,(address,bytes)[])\":{\"notice\":\"Backwards-compatible with Multicall2Aggregate calls without requiring success\"},\"tryBlockAndAggregate(bool,(address,bytes)[])\":{\"notice\":\"Backwards-compatible with Multicall2Aggregate calls and allow failures using tryAggregate\"},\"whitelistedSenders(address)\":{\"notice\":\"Callers who can call state changing public functions.\"}},\"notice\":\"Aggregate results from multiple function calls but only allows a whitelisted set of msg.senders.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/external/PermissionedMulticall3.sol\":\"PermissionedMulticall3\"},\"debug\":{\"revertStrings\":\"strip\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby disabling any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xba43b97fba0d32eb4254f6a5a297b39a19a247082a02d6e69349e071e2946218\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n\\n function _contextSuffixLength() internal view virtual returns (uint256) {\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xa92e4fa126feb6907daa0513ddd816b2eb91f30a808de54f63c17d0e162c3439\",\"license\":\"MIT\"},\"contracts/external/PermissionedMulticall3.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0; // Bumped version\\n\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n/**\\n * This is a simple fork of Multicall3 (the version found in this repo) that makes the contract Ownable\\n * and adds a whitelist of addresses that are allowed to call the contract's external functions.\\n **/\\n\\n/// @title PermissionedMulticall3\\n/// @notice Aggregate results from multiple function calls but only allows a whitelisted set of msg.senders.\\n/// @dev This contract is designed to be used as part of a permissioned system where this contract can be whitelisted\\n/// to call other contracts on behalf of the whitelisted senders. The benefit is that the whitelisted senders\\n/// can still batch call permissioned functions with unpermissioned functions by going through this contract.\\n/// @dev Multicall & Multicall2 backwards-compatible\\n/// @dev Aggregate methods are marked `payable` to save 24 gas per call\\n/// @author Michael Elliot \\n/// @author Joshua Levine \\n/// @author Nick Johnson \\n/// @author Andreas Bigger \\n/// @author Matt Solomon \\ncontract PermissionedMulticall3 is Ownable {\\n /// @notice Callers who can call state changing public functions.\\n mapping (address => bool) public whitelistedSenders;\\n\\n struct Call {\\n address target;\\n bytes callData;\\n }\\n\\n struct Call3 {\\n address target;\\n bool allowFailure;\\n bytes callData;\\n }\\n\\n struct Call3Value {\\n address target;\\n bool allowFailure;\\n uint256 value;\\n bytes callData;\\n }\\n\\n struct Result {\\n bool success;\\n bytes returnData;\\n }\\n\\n modifier onlyWhitelisted() {\\n require(whitelistedSenders[msg.sender], \\\"sender not whitelisted\\\");\\n _;\\n }\\n\\n function whitelist(address[] calldata senders, bool[] calldata value) external onlyOwner {\\n require(senders.length == value.length, \\\"senders and values length mismatch\\\");\\n for (uint256 i = 0; i < senders.length; i++) {\\n whitelistedSenders[senders[i]] = value[i];\\n }\\n }\\n\\n /// @notice Backwards-compatible call aggregation with Multicall\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return returnData An array of bytes containing the responses\\n function aggregate(Call[] calldata calls) public onlyWhitelisted payable returns (uint256 blockNumber, bytes[] memory returnData) {\\n blockNumber = block.number;\\n uint256 length = calls.length;\\n returnData = new bytes[](length);\\n Call calldata call;\\n for (uint256 i = 0; i < length; ) {\\n bool success;\\n call = calls[i];\\n (success, returnData[i]) = call.target.call(call.callData);\\n require(success, \\\"Multicall3: call failed\\\");\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls without requiring success\\n /// @param requireSuccess If true, require all calls to succeed\\n /// @param calls An array of Call structs\\n /// @return returnData An array of Result structs\\n function tryAggregate(bool requireSuccess, Call[] calldata calls)\\n public\\n payable\\n onlyWhitelisted\\n returns (Result[] memory returnData)\\n {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call calldata call;\\n for (uint256 i = 0; i < length; ) {\\n Result memory result = returnData[i];\\n call = calls[i];\\n (result.success, result.returnData) = call.target.call(call.callData);\\n if (requireSuccess) require(result.success, \\\"Multicall3: call failed\\\");\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)\\n public\\n payable\\n onlyWhitelisted\\n returns (\\n uint256 blockNumber,\\n bytes32 blockHash,\\n Result[] memory returnData\\n )\\n {\\n blockNumber = block.number;\\n blockHash = blockhash(block.number);\\n returnData = tryAggregate(requireSuccess, calls);\\n }\\n\\n /// @notice Backwards-compatible with Multicall2\\n /// @notice Aggregate calls and allow failures using tryAggregate\\n /// @param calls An array of Call structs\\n /// @return blockNumber The block number where the calls were executed\\n /// @return blockHash The hash of the block where the calls were executed\\n /// @return returnData An array of Result structs\\n function blockAndAggregate(Call[] calldata calls)\\n public\\n payable\\n onlyWhitelisted\\n returns (\\n uint256 blockNumber,\\n bytes32 blockHash,\\n Result[] memory returnData\\n )\\n {\\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\\n }\\n\\n /// @notice Aggregate calls, ensuring each returns success if required\\n /// @param calls An array of Call3 structs\\n /// @return returnData An array of Result structs\\n function aggregate3(Call3[] calldata calls) public payable onlyWhitelisted returns (Result[] memory returnData) {\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3 calldata calli;\\n for (uint256 i = 0; i < length; ) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n (result.success, result.returnData) = calli.target.call(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x64)\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Aggregate calls with a msg value\\n /// @notice Reverts if msg.value is less than the sum of the call values\\n /// @param calls An array of Call3Value structs\\n /// @return returnData An array of Result structs\\n function aggregate3Value(Call3Value[] calldata calls) public payable onlyWhitelisted returns (Result[] memory returnData) {\\n uint256 valAccumulator;\\n uint256 length = calls.length;\\n returnData = new Result[](length);\\n Call3Value calldata calli;\\n for (uint256 i = 0; i < length; ) {\\n Result memory result = returnData[i];\\n calli = calls[i];\\n uint256 val = calli.value;\\n // Humanity will be a Type V Kardashev Civilization before this overflows - andreas\\n // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256\\n unchecked {\\n valAccumulator += val;\\n }\\n (result.success, result.returnData) = calli.target.call{ value: val }(calli.callData);\\n assembly {\\n // Revert if the call fails and failure is not allowed\\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\\n // set \\\"Error(string)\\\" signature: bytes32(bytes4(keccak256(\\\"Error(string)\\\")))\\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\\n // set data offset\\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\\n // set length of revert string\\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\\n // set revert string: bytes32(abi.encodePacked(\\\"Multicall3: call failed\\\"))\\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\\n revert(0x00, 0x84)\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n // Finally, make sure the msg.value = SUM(call[0...i].value)\\n require(msg.value == valAccumulator, \\\"Multicall3: value mismatch\\\");\\n }\\n\\n /// @notice Returns the block hash for the given block number\\n /// @param blockNumber The block number\\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\\n blockHash = blockhash(blockNumber);\\n }\\n\\n /// @notice Returns the block number\\n function getBlockNumber() public view returns (uint256 blockNumber) {\\n blockNumber = block.number;\\n }\\n\\n /// @notice Returns the block coinbase\\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\\n coinbase = block.coinbase;\\n }\\n\\n /// @notice Returns the block difficulty\\n function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {\\n difficulty = block.difficulty;\\n }\\n\\n /// @notice Returns the block gas limit\\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\\n gaslimit = block.gaslimit;\\n }\\n\\n /// @notice Returns the block timestamp\\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\\n timestamp = block.timestamp;\\n }\\n\\n /// @notice Returns the (ETH) balance of a given address\\n function getEthBalance(address addr) public view returns (uint256 balance) {\\n balance = addr.balance;\\n }\\n\\n /// @notice Returns the block hash of the last block\\n function getLastBlockHash() public view returns (bytes32 blockHash) {\\n unchecked {\\n blockHash = blockhash(block.number - 1);\\n }\\n }\\n\\n /// @notice Gets the base fee of the given block\\n /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain\\n function getBasefee() public view returns (uint256 basefee) {\\n basefee = block.basefee;\\n }\\n\\n /// @notice Returns the chain id\\n function getChainId() public view returns (uint256 chainid) {\\n chainid = block.chainid;\\n }\\n}\\n\",\"keccak256\":\"0x6eae682c741291bb7ba48eec0c6bfcb30fe9b260bc6885512098d48400db5274\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080806040523461005a575f8054336001600160a01b0319821681178355916001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3611183908161005f8239f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c80630f28c97d14610164578063174dea711461015f578063252dba421461015a578063272efc691461015557806327e86d6e146101505780633408e4701461014b578063399542e9146101465780633e64a6961461014157806342cbb15c1461013c5780634d2301cc1461013757806355e23fa814610132578063715018a61461012d57806372425d9d1461012857806382ad56cb1461012357806386d516e81461011e5780638da5cb5b14610119578063a8b0574e14610114578063bce38bd71461010f578063c3077fa91461010a578063ee82ac5e146101055763f2fde38b14610100575f80fd5b610ceb565b610caf565b610bfd565b610bd4565b610b9c565b610b4c565b610b14565b610a21565b6109e9565b61094f565b610847565b610801565b6107c9565b610791565b610754565b61069f565b610644565b6105d8565b6104c5565b61031b565b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051428152f35b5f80fd5b9181601f8401121561019c5782359167ffffffffffffffff831161019c576020808501948460051b01011161019c57565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261019c576004359067ffffffffffffffff821161019c5761021a916004016101a0565b9091565b91908251928382525f5b8481106102665750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b602081830181015184830182015201610228565b908082519081815260208091019281808460051b8301019501935f915b8483106102a75750505050505090565b90919293949584806102f7837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528a51836040918051151584520151918185820152019061021e565b9801930193019194939290610297565b90602061031892818152019061027a565b90565b610324366101d1565b335f526001602091600160205260409260ff60405f2054161561019c575f9461034c83610e32565b945f5b84811061037557610371876103658a3414610d9d565b60405191829182610307565b0390f35b61037f8188610edd565b518461038c838887610ef6565b916103d75f8087860135809e019d6103a387610f36565b906103b16060890189610f40565b91906103c18c5180948193610f91565b03925af16103cd610f9e565b8385015215158252565b5191013517156103e857850161034f565b837f08c379a0000000000000000000000000000000000000000000000000000000005f5260045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260845ffd5b906040820190825260206040602084015283518092526060830192602060608460051b8301019501935f915b8483106104795750505050505090565b90919293949584806104b5837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa086600196030187528a5161021e565b9801930193019194939290610469565b6104ce366101d1565b335f5260019160206001602052604060ff60405f2054161561019c576104fb6104f685610e1a565b610dd1565b938085527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061052982610e1a565b01835f5b8281106105aa575050505f5b81811061054f576040518061037188438361043d565b806105a45f806105618b95878b610ff7565b8161057861056e83610f36565b928b810190610f40565b91906105888b5180948193610f91565b03925af1610594610f9e565b61059e848b610edd565b52610d9d565b01610539565b606082828a01015201849061052d565b73ffffffffffffffffffffffffffffffffffffffff81160361019c57565b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff600435610628816105ba565b165f526001602052602060ff60405f2054166040519015158152f35b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760206040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4301408152f35b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051468152f35b8015150361019c57565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261019c57600435610718816106d7565b916024359067ffffffffffffffff821161019c5761021a916004016101a0565b610318939260609282526020820152816040820152019061027a565b61075d366106e1565b919091335f52600160205260ff60405f2054161561019c576103719261078292611087565b60405191829143404384610738565b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051488152f35b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051438152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57602060043561083e816105ba565b31604051908152f35b3461019c576040807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5767ffffffffffffffff9060043582811161019c576108999036906004016101a0565b9260243590811161019c576108b29036906004016101a0565b9290936108bd61112d565b83810361019c575f5b8181106108cf57005b806108dd6001928789611037565b356108e7816106d7565b73ffffffffffffffffffffffffffffffffffffffff610907838689611037565b35610911816105ba565b165f5282602052845f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055016108c6565b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5761098561112d565b5f73ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051448152f35b610a2a366101d1565b90335f526001602092600160205260409360ff60405f2054161561019c57610a5182610e32565b935f5b838110610a6957604051806103718882610307565b610a738187610edd565b5183610a80838786611047565b91610aae5f808c6103c182610a9489610f36565b92610aa1818b018b610f40565b9390915180948193610f91565b519101351715610abf578401610a54565b827f08c379a0000000000000000000000000000000000000000000000000000000005f5260045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260645ffd5b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051458152f35b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57602073ffffffffffffffffffffffffffffffffffffffff5f5416604051908152f35b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051418152f35b610371610be9610be3366106e1565b91611087565b60405191829160208352602083019061027a565b610c06366101d1565b90335f52600191602091600160205260409260ff60405f2054161561019c57610c2e83610e32565b935f5b848110610c4a5760405180610371884380409084610738565b80610ca9610c59899389610edd565b515f80610c67858b8b610ff7565b81610c80823592610c77846105ba565b8b810190610f40565b9190828b519384928337810182815203925af1610c9b610f9e565b878301521515809152610d9d565b01610c31565b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051600435408152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57600435610d26816105ba565b610d2e61112d565b73ffffffffffffffffffffffffffffffffffffffff80911690811561019c575f54827fffffffffffffffffffffffff00000000000000000000000000000000000000008216175f55167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b1561019c57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f604051930116820182811067ffffffffffffffff821117610e1557604052565b610da4565b67ffffffffffffffff8111610e155760051b60200190565b90610e3f6104f683610e1a565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610e6d8294610e1a565b015f5b818110610e7c57505050565b604090815182810181811067ffffffffffffffff821117610e1557602093525f815282606081830152828601015201610e70565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b8051821015610ef15760209160051b010190565b610eb0565b9190811015610ef15760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818136030182121561019c570190565b35610318816105ba565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561019c570180359067ffffffffffffffff821161019c5760200191813603831361019c57565b908092918237015f815290565b3d15610ff2573d9067ffffffffffffffff8211610e1557610fe660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601610dd1565b9182523d5f602084013e565b606090565b9190811015610ef15760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561019c570190565b9190811015610ef15760051b0190565b9190811015610ef15760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18136030182121561019c570190565b91335f52600191602093600160205260409460ff60405f2054161561019c576110af84610e32565b955f5b8581106110c3575050505050505090565b806110cf88928a610edd565b51855f806110de858c8c610ff7565b816110ee823592610c77846105ba565b9190828b519384928337810182815203925af1611109610f9e565b87840152151580925261111e575b50016110b2565b61112790610d9d565b5f611117565b73ffffffffffffffffffffffffffffffffffffffff5f5416330361019c5756fea26469706673582212209eca82ca5db63b46f49f3bde52ab2c297705a6b6b03786ac7c85932d21ca626a64736f6c63430008170033", + "deployedBytecode": "0x60806040526004361015610011575f80fd5b5f3560e01c80630f28c97d14610164578063174dea711461015f578063252dba421461015a578063272efc691461015557806327e86d6e146101505780633408e4701461014b578063399542e9146101465780633e64a6961461014157806342cbb15c1461013c5780634d2301cc1461013757806355e23fa814610132578063715018a61461012d57806372425d9d1461012857806382ad56cb1461012357806386d516e81461011e5780638da5cb5b14610119578063a8b0574e14610114578063bce38bd71461010f578063c3077fa91461010a578063ee82ac5e146101055763f2fde38b14610100575f80fd5b610ceb565b610caf565b610bfd565b610bd4565b610b9c565b610b4c565b610b14565b610a21565b6109e9565b61094f565b610847565b610801565b6107c9565b610791565b610754565b61069f565b610644565b6105d8565b6104c5565b61031b565b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051428152f35b5f80fd5b9181601f8401121561019c5782359167ffffffffffffffff831161019c576020808501948460051b01011161019c57565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261019c576004359067ffffffffffffffff821161019c5761021a916004016101a0565b9091565b91908251928382525f5b8481106102665750507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f845f6020809697860101520116010190565b602081830181015184830182015201610228565b908082519081815260208091019281808460051b8301019501935f915b8483106102a75750505050505090565b90919293949584806102f7837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086600196030187528a51836040918051151584520151918185820152019061021e565b9801930193019194939290610297565b90602061031892818152019061027a565b90565b610324366101d1565b335f526001602091600160205260409260ff60405f2054161561019c575f9461034c83610e32565b945f5b84811061037557610371876103658a3414610d9d565b60405191829182610307565b0390f35b61037f8188610edd565b518461038c838887610ef6565b916103d75f8087860135809e019d6103a387610f36565b906103b16060890189610f40565b91906103c18c5180948193610f91565b03925af16103cd610f9e565b8385015215158252565b5191013517156103e857850161034f565b837f08c379a0000000000000000000000000000000000000000000000000000000005f5260045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260845ffd5b906040820190825260206040602084015283518092526060830192602060608460051b8301019501935f915b8483106104795750505050505090565b90919293949584806104b5837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa086600196030187528a5161021e565b9801930193019194939290610469565b6104ce366101d1565b335f5260019160206001602052604060ff60405f2054161561019c576104fb6104f685610e1a565b610dd1565b938085527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061052982610e1a565b01835f5b8281106105aa575050505f5b81811061054f576040518061037188438361043d565b806105a45f806105618b95878b610ff7565b8161057861056e83610f36565b928b810190610f40565b91906105888b5180948193610f91565b03925af1610594610f9e565b61059e848b610edd565b52610d9d565b01610539565b606082828a01015201849061052d565b73ffffffffffffffffffffffffffffffffffffffff81160361019c57565b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5773ffffffffffffffffffffffffffffffffffffffff600435610628816105ba565b165f526001602052602060ff60405f2054166040519015158152f35b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5760206040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4301408152f35b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051468152f35b8015150361019c57565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261019c57600435610718816106d7565b916024359067ffffffffffffffff821161019c5761021a916004016101a0565b610318939260609282526020820152816040820152019061027a565b61075d366106e1565b919091335f52600160205260ff60405f2054161561019c576103719261078292611087565b60405191829143404384610738565b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051488152f35b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051438152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57602060043561083e816105ba565b31604051908152f35b3461019c576040807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5767ffffffffffffffff9060043582811161019c576108999036906004016101a0565b9260243590811161019c576108b29036906004016101a0565b9290936108bd61112d565b83810361019c575f5b8181106108cf57005b806108dd6001928789611037565b356108e7816106d7565b73ffffffffffffffffffffffffffffffffffffffff610907838689611037565b35610911816105ba565b165f5282602052845f209060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055016108c6565b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c5761098561112d565b5f73ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051448152f35b610a2a366101d1565b90335f526001602092600160205260409360ff60405f2054161561019c57610a5182610e32565b935f5b838110610a6957604051806103718882610307565b610a738187610edd565b5183610a80838786611047565b91610aae5f808c6103c182610a9489610f36565b92610aa1818b018b610f40565b9390915180948193610f91565b519101351715610abf578401610a54565b827f08c379a0000000000000000000000000000000000000000000000000000000005f5260045260176024527f4d756c746963616c6c333a2063616c6c206661696c656400000000000000000060445260645ffd5b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051458152f35b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57602073ffffffffffffffffffffffffffffffffffffffff5f5416604051908152f35b3461019c575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051418152f35b610371610be9610be3366106e1565b91611087565b60405191829160208352602083019061027a565b610c06366101d1565b90335f52600191602091600160205260409260ff60405f2054161561019c57610c2e83610e32565b935f5b848110610c4a5760405180610371884380409084610738565b80610ca9610c59899389610edd565b515f80610c67858b8b610ff7565b81610c80823592610c77846105ba565b8b810190610f40565b9190828b519384928337810182815203925af1610c9b610f9e565b878301521515809152610d9d565b01610c31565b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c576020604051600435408152f35b3461019c5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019c57600435610d26816105ba565b610d2e61112d565b73ffffffffffffffffffffffffffffffffffffffff80911690811561019c575f54827fffffffffffffffffffffffff00000000000000000000000000000000000000008216175f55167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b1561019c57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f604051930116820182811067ffffffffffffffff821117610e1557604052565b610da4565b67ffffffffffffffff8111610e155760051b60200190565b90610e3f6104f683610e1a565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610e6d8294610e1a565b015f5b818110610e7c57505050565b604090815182810181811067ffffffffffffffff821117610e1557602093525f815282606081830152828601015201610e70565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b8051821015610ef15760209160051b010190565b610eb0565b9190811015610ef15760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818136030182121561019c570190565b35610318816105ba565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561019c570180359067ffffffffffffffff821161019c5760200191813603831361019c57565b908092918237015f815290565b3d15610ff2573d9067ffffffffffffffff8211610e1557610fe660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011601610dd1565b9182523d5f602084013e565b606090565b9190811015610ef15760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18136030182121561019c570190565b9190811015610ef15760051b0190565b9190811015610ef15760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18136030182121561019c570190565b91335f52600191602093600160205260409460ff60405f2054161561019c576110af84610e32565b955f5b8581106110c3575050505050505090565b806110cf88928a610edd565b51855f806110de858c8c610ff7565b816110ee823592610c77846105ba565b9190828b519384928337810182815203925af1611109610f9e565b87840152151580925261111e575b50016110b2565b61112790610d9d565b5f611117565b73ffffffffffffffffffffffffffffffffffffffff5f5416330361019c5756fea26469706673582212209eca82ca5db63b46f49f3bde52ab2c297705a6b6b03786ac7c85932d21ca626a64736f6c63430008170033", "devdoc": { "author": "Michael Elliot Joshua Levine Nick Johnson Andreas Bigger Matt Solomon ", "details": "This contract is designed to be used as part of a permissioned system where this contract can be whitelisted to call other contracts on behalf of the whitelisted senders. The benefit is that the whitelisted senders can still batch call permissioned functions with unpermissioned functions by going through this contract.Multicall & Multicall2 backwards-compatibleAggregate methods are marked `payable` to save 24 gas per call", @@ -507,6 +611,15 @@ "blockNumber": "The block number" } }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, "tryAggregate(bool,(address,bytes)[])": { "params": { "calls": "An array of Call structs", @@ -580,13 +693,51 @@ }, "tryBlockAndAggregate(bool,(address,bytes)[])": { "notice": "Backwards-compatible with Multicall2Aggregate calls and allow failures using tryAggregate" + }, + "whitelistedSenders(address)": { + "notice": "Callers who can call state changing public functions." } }, "notice": "Aggregate results from multiple function calls but only allows a whitelisted set of msg.senders.", "version": 1 }, "storageLayout": { - "storage": [], - "types": null + "storage": [ + { + "astId": 7, + "contract": "contracts/external/PermissionedMulticall3.sol:PermissionedMulticall3", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 153, + "contract": "contracts/external/PermissionedMulticall3.sol:PermissionedMulticall3", + "label": "whitelistedSenders", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + } + } } } diff --git a/deployments/bsc/solcInputs/8cf77b572b3c86de2e87d5cc0dc68812.json b/deployments/bsc/solcInputs/8cf77b572b3c86de2e87d5cc0dc68812.json new file mode 100644 index 000000000..18e4c88db --- /dev/null +++ b/deployments/bsc/solcInputs/8cf77b572b3c86de2e87d5cc0dc68812.json @@ -0,0 +1,43 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" + }, + "contracts/external/PermissionedMulticall3.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0; // Bumped version\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * This is a simple fork of Multicall3 (the version found in this repo) that makes the contract Ownable\n * and adds a whitelist of addresses that are allowed to call the contract's external functions.\n **/\n\n/// @title PermissionedMulticall3\n/// @notice Aggregate results from multiple function calls but only allows a whitelisted set of msg.senders.\n/// @dev This contract is designed to be used as part of a permissioned system where this contract can be whitelisted\n/// to call other contracts on behalf of the whitelisted senders. The benefit is that the whitelisted senders\n/// can still batch call permissioned functions with unpermissioned functions by going through this contract.\n/// @dev Multicall & Multicall2 backwards-compatible\n/// @dev Aggregate methods are marked `payable` to save 24 gas per call\n/// @author Michael Elliot \n/// @author Joshua Levine \n/// @author Nick Johnson \n/// @author Andreas Bigger \n/// @author Matt Solomon \ncontract PermissionedMulticall3 is Ownable {\n /// @notice Callers who can call state changing public functions.\n mapping (address => bool) public whitelistedSenders;\n\n struct Call {\n address target;\n bytes callData;\n }\n\n struct Call3 {\n address target;\n bool allowFailure;\n bytes callData;\n }\n\n struct Call3Value {\n address target;\n bool allowFailure;\n uint256 value;\n bytes callData;\n }\n\n struct Result {\n bool success;\n bytes returnData;\n }\n\n modifier onlyWhitelisted() {\n require(whitelistedSenders[msg.sender], \"sender not whitelisted\");\n _;\n }\n\n function whitelist(address[] calldata senders, bool[] calldata value) external onlyOwner {\n require(senders.length == value.length, \"senders and values length mismatch\");\n for (uint256 i = 0; i < senders.length; i++) {\n whitelistedSenders[senders[i]] = value[i];\n }\n }\n\n /// @notice Backwards-compatible call aggregation with Multicall\n /// @param calls An array of Call structs\n /// @return blockNumber The block number where the calls were executed\n /// @return returnData An array of bytes containing the responses\n function aggregate(Call[] calldata calls) public onlyWhitelisted payable returns (uint256 blockNumber, bytes[] memory returnData) {\n blockNumber = block.number;\n uint256 length = calls.length;\n returnData = new bytes[](length);\n Call calldata call;\n for (uint256 i = 0; i < length; ) {\n bool success;\n call = calls[i];\n (success, returnData[i]) = call.target.call(call.callData);\n require(success, \"Multicall3: call failed\");\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Backwards-compatible with Multicall2\n /// @notice Aggregate calls without requiring success\n /// @param requireSuccess If true, require all calls to succeed\n /// @param calls An array of Call structs\n /// @return returnData An array of Result structs\n function tryAggregate(bool requireSuccess, Call[] calldata calls)\n public\n payable\n onlyWhitelisted\n returns (Result[] memory returnData)\n {\n uint256 length = calls.length;\n returnData = new Result[](length);\n Call calldata call;\n for (uint256 i = 0; i < length; ) {\n Result memory result = returnData[i];\n call = calls[i];\n (result.success, result.returnData) = call.target.call(call.callData);\n if (requireSuccess) require(result.success, \"Multicall3: call failed\");\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Backwards-compatible with Multicall2\n /// @notice Aggregate calls and allow failures using tryAggregate\n /// @param calls An array of Call structs\n /// @return blockNumber The block number where the calls were executed\n /// @return blockHash The hash of the block where the calls were executed\n /// @return returnData An array of Result structs\n function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls)\n public\n payable\n onlyWhitelisted\n returns (\n uint256 blockNumber,\n bytes32 blockHash,\n Result[] memory returnData\n )\n {\n blockNumber = block.number;\n blockHash = blockhash(block.number);\n returnData = tryAggregate(requireSuccess, calls);\n }\n\n /// @notice Backwards-compatible with Multicall2\n /// @notice Aggregate calls and allow failures using tryAggregate\n /// @param calls An array of Call structs\n /// @return blockNumber The block number where the calls were executed\n /// @return blockHash The hash of the block where the calls were executed\n /// @return returnData An array of Result structs\n function blockAndAggregate(Call[] calldata calls)\n public\n payable\n onlyWhitelisted\n returns (\n uint256 blockNumber,\n bytes32 blockHash,\n Result[] memory returnData\n )\n {\n (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);\n }\n\n /// @notice Aggregate calls, ensuring each returns success if required\n /// @param calls An array of Call3 structs\n /// @return returnData An array of Result structs\n function aggregate3(Call3[] calldata calls) public payable onlyWhitelisted returns (Result[] memory returnData) {\n uint256 length = calls.length;\n returnData = new Result[](length);\n Call3 calldata calli;\n for (uint256 i = 0; i < length; ) {\n Result memory result = returnData[i];\n calli = calls[i];\n (result.success, result.returnData) = calli.target.call(calli.callData);\n assembly {\n // Revert if the call fails and failure is not allowed\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\n // set \"Error(string)\" signature: bytes32(bytes4(keccak256(\"Error(string)\")))\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n // set data offset\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\n // set length of revert string\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\n // set revert string: bytes32(abi.encodePacked(\"Multicall3: call failed\"))\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\n revert(0x00, 0x64)\n }\n }\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Aggregate calls with a msg value\n /// @notice Reverts if msg.value is less than the sum of the call values\n /// @param calls An array of Call3Value structs\n /// @return returnData An array of Result structs\n function aggregate3Value(Call3Value[] calldata calls) public payable onlyWhitelisted returns (Result[] memory returnData) {\n uint256 valAccumulator;\n uint256 length = calls.length;\n returnData = new Result[](length);\n Call3Value calldata calli;\n for (uint256 i = 0; i < length; ) {\n Result memory result = returnData[i];\n calli = calls[i];\n uint256 val = calli.value;\n // Humanity will be a Type V Kardashev Civilization before this overflows - andreas\n // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256\n unchecked {\n valAccumulator += val;\n }\n (result.success, result.returnData) = calli.target.call{ value: val }(calli.callData);\n assembly {\n // Revert if the call fails and failure is not allowed\n // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)`\n if iszero(or(calldataload(add(calli, 0x20)), mload(result))) {\n // set \"Error(string)\" signature: bytes32(bytes4(keccak256(\"Error(string)\")))\n mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000)\n // set data offset\n mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020)\n // set length of revert string\n mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017)\n // set revert string: bytes32(abi.encodePacked(\"Multicall3: call failed\"))\n mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000)\n revert(0x00, 0x84)\n }\n }\n unchecked {\n ++i;\n }\n }\n // Finally, make sure the msg.value = SUM(call[0...i].value)\n require(msg.value == valAccumulator, \"Multicall3: value mismatch\");\n }\n\n /// @notice Returns the block hash for the given block number\n /// @param blockNumber The block number\n function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {\n blockHash = blockhash(blockNumber);\n }\n\n /// @notice Returns the block number\n function getBlockNumber() public view returns (uint256 blockNumber) {\n blockNumber = block.number;\n }\n\n /// @notice Returns the block coinbase\n function getCurrentBlockCoinbase() public view returns (address coinbase) {\n coinbase = block.coinbase;\n }\n\n /// @notice Returns the block difficulty\n function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {\n difficulty = block.difficulty;\n }\n\n /// @notice Returns the block gas limit\n function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {\n gaslimit = block.gaslimit;\n }\n\n /// @notice Returns the block timestamp\n function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {\n timestamp = block.timestamp;\n }\n\n /// @notice Returns the (ETH) balance of a given address\n function getEthBalance(address addr) public view returns (uint256 balance) {\n balance = addr.balance;\n }\n\n /// @notice Returns the block hash of the last block\n function getLastBlockHash() public view returns (bytes32 blockHash) {\n unchecked {\n blockHash = blockhash(block.number - 1);\n }\n }\n\n /// @notice Gets the base fee of the given block\n /// @notice Can revert if the BASEFEE opcode is not implemented by the given chain\n function getBasefee() public view returns (uint256 basefee) {\n basefee = block.basefee;\n }\n\n /// @notice Returns the chain id\n function getChainId() public view returns (uint256 chainid) {\n chainid = block.chainid;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "viaIR": true, + "debug": { + "revertStrings": "strip" + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +}