diff --git a/deploy/consts.ts b/deploy/consts.ts index 5e2937dd1..c943bbd7e 100644 --- a/deploy/consts.ts +++ b/deploy/consts.ts @@ -43,8 +43,8 @@ export const L1_ADDRESS_MAP: { [key: number]: { [contractName: string]: string } blastDaiRetriever: "0x98Dd57048d7d5337e92D9102743528ea4Fea64aB", redstoneCrossDomainMessenger: "0x592C1299e0F8331D81A28C0FC7352Da24eDB444a", redstoneStandardBridge: "0xc473ca7E02af24c129c2eEf51F2aDf0411c1Df69", - zoraCrossDomainMessenger: "0x363B4B1ADa52E50353f746999bd9E94395190d2C", - zoraStandardBridge: "0xbF6acaF315477b15D638bf4d91eA48FA79b58335", + zoraCrossDomainMessenger: "0xdC40a14d9abd6F410226f1E6de71aE03441ca506", + zoraStandardBridge: "0x3e2Ea9B92B7E48A52296fD261dc26fd995284631", }, 4: { weth: "0xc778417E063141139Fce010982780140Aa0cD5Ab", diff --git a/deployments/README.md b/deployments/README.md index e34cda379..28197e970 100644 --- a/deployments/README.md +++ b/deployments/README.md @@ -92,7 +92,7 @@ | Contract Name | Address | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------ | -| Redstone_SpokePool | [0x28077B47Cd03326De7838926A63699849DD4fa87](https://explorer.redstone.xyz/address/0x28077B47Cd03326De7838926A63699849DD4fa87) | +| Redstone_SpokePool | [0x13fDac9F9b4777705db45291bbFF3c972c6d1d97](https://explorer.redstone.xyz/address/0x13fDac9F9b4777705db45291bbFF3c972c6d1d97) | | MulticallHandler | [0x924a9f036260DdD5808007E1AA95f08eD08aA569](https://explorer.redstone.xyz/address/0x924a9f036260DdD5808007E1AA95f08eD08aA569) | ## Scroll mainnet (534352) @@ -101,3 +101,10 @@ | ---------------- | ----------------------------------------------------------------------------------------------------------------------- | | Scroll_SpokePool | [0x3baD7AD0728f9917d1Bf08af5782dCbD516cDd96](https://scrollscan.com/address/0x3baD7AD0728f9917d1Bf08af5782dCbD516cDd96) | | MulticallHandler | [0x924a9f036260DdD5808007E1AA95f08eD08aA569](https://scrollscan.com/address/0x924a9f036260DdD5808007E1AA95f08eD08aA569) | + +## Zora mainnet (7777777) + +| Contract Name | Address | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| Zora_SpokePool | [0x13fDac9F9b4777705db45291bbFF3c972c6d1d97](https://zorascan.xyz/address/0x13fDac9F9b4777705db45291bbFF3c972c6d1d97) | +| MulticallHandler | [0x924a9f036260DdD5808007E1AA95f08eD08aA569](https://explorer.redstone.xyz/address/0x924a9f036260DdD5808007E1AA95f08eD08aA569) | diff --git a/deployments/deployments.json b/deployments/deployments.json index 51ef946c6..7afa90718 100644 --- a/deployments/deployments.json +++ b/deployments/deployments.json @@ -26,7 +26,7 @@ "Blast_DaiRetriever": { "address": "0x98Dd57048d7d5337e92D9102743528ea4Fea64aB", "blockNumber": 20378862 }, "Blast_RescueAdapter": { "address": "0xE5Dea263511F5caC27b15cBd58Ff103F4Ce90957", "blockNumber": 20378872 }, "Redstone_Adapter": { "address": "0x188F8C95B7cfB7993B53a4F643efa687916f73fA", "blockNumber": 20432774 }, - "Zora_Adapter": { "address": "0xa27fb9f2A22F8dA4cBF155e9795A43488004AAc3", "blockNumber": 20468487 } + "Zora_Adapter": { "address": "0x024f2fc31cbdd8de17194b1892c834f98ef5169b", "blockNumber": 20512287 } }, "10": { "SpokePool": { "address": "0x6f26Bf09B1C792e3228e5467807a900A503c0281", "blockNumber": 93903076 }, @@ -132,6 +132,7 @@ "MulticallHandler": { "address": "0x924a9f036260DdD5808007E1AA95f08eD08aA569", "blockNumber": 7489978 } }, "7777777": { + "SpokePool": { "address": "0x13fDac9F9b4777705db45291bbFF3c972c6d1d97", "blockNumber": 18382867 }, "SpokePoolVerifier": { "address": "0xB4A8d45647445EA9FC3E1058096142390683dBC2", "blockNumber": 18120222 }, "MulticallHandler": { "address": "0x924a9f036260DdD5808007E1AA95f08eD08aA569", "blockNumber": 18119854 } }, diff --git a/deployments/mainnet/Zora_Adapter.json b/deployments/mainnet/Zora_Adapter.json new file mode 100644 index 000000000..b0edaf810 --- /dev/null +++ b/deployments/mainnet/Zora_Adapter.json @@ -0,0 +1,295 @@ +{ + "address": "0x024F2fC31CBDD8de17194b1892c834f98Ef5169b", + "abi": [ + { + "inputs": [ + { + "internalType": "contract WETH9Interface", + "name": "_l1Weth", + "type": "address" + }, + { + "internalType": "address", + "name": "_crossDomainMessenger", + "type": "address" + }, + { + "internalType": "contract IL1StandardBridge", + "name": "_l1StandardBridge", + "type": "address" + }, + { + "internalType": "contract IERC20", + "name": "_l1Usdc", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "MessageRelayed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "l2Token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "TokensRelayed", + "type": "event" + }, + { + "inputs": [], + "name": "L1_STANDARD_BRIDGE", + "outputs": [ + { + "internalType": "contract IL1StandardBridge", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "L1_WETH", + "outputs": [ + { + "internalType": "contract WETH9Interface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "L2_GAS_LIMIT", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MESSENGER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cctpTokenMessenger", + "outputs": [ + { + "internalType": "contract ITokenMessenger", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "recipientCircleDomainId", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "relayMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "l1Token", + "type": "address" + }, + { + "internalType": "address", + "name": "l2Token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "relayTokens", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "usdcToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x9a4dd99e13bf8dea50e5121f5ad1d7187054cf78b6f0efb1318f384a18e11642", + "receipt": { + "to": null, + "from": "0x9A8f92a830A5cB89a3816e3D267CB7791c16b04D", + "contractAddress": "0x024F2fC31CBDD8de17194b1892c834f98Ef5169b", + "transactionIndex": 18, + "gasUsed": "977784", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf5fe4d7be2d17806247f71f0d529e60d731f1ac5e1da49c2576c3ffdfb1aaaee", + "transactionHash": "0x9a4dd99e13bf8dea50e5121f5ad1d7187054cf78b6f0efb1318f384a18e11642", + "logs": [], + "blockNumber": 20512287, + "cumulativeGasUsed": "6295399", + "status": 1, + "byzantium": true + }, + "args": [ + "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "0xdC40a14d9abd6F410226f1E6de71aE03441ca506", + "0x3e2Ea9B92B7E48A52296fD261dc26fd995284631", + "0x0000000000000000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "8c8d8b75dd96f63e54bfa124522c7f29", + "metadata": "{\"compiler\":{\"version\":\"0.8.23+commit.f704f362\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract WETH9Interface\",\"name\":\"_l1Weth\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_crossDomainMessenger\",\"type\":\"address\"},{\"internalType\":\"contract IL1StandardBridge\",\"name\":\"_l1StandardBridge\",\"type\":\"address\"},{\"internalType\":\"contract IERC20\",\"name\":\"_l1Usdc\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"MessageRelayed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"TokensRelayed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"L1_STANDARD_BRIDGE\",\"outputs\":[{\"internalType\":\"contract IL1StandardBridge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L1_WETH\",\"outputs\":[{\"internalType\":\"contract WETH9Interface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"L2_GAS_LIMIT\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cctpTokenMessenger\",\"outputs\":[{\"internalType\":\"contract ITokenMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"recipientCircleDomainId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"relayMessage\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"relayTokens\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usdcToken\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"custom:security-contact\":\"bugs@across.to\",\"details\":\"Public functions calling external contracts do not guard against reentrancy because they are expected to be called via delegatecall, which will execute this contract's logic within the context of the originating contract. For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods that call this contract's logic guard against reentrancy.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_crossDomainMessenger\":\"XDomainMessenger Zora system contract.\",\"_l1StandardBridge\":\"Standard bridge contract.\",\"_l1Usdc\":\"USDC address on L1.\",\"_l1Weth\":\"WETH address on L1.\"}},\"relayMessage(address,bytes)\":{\"params\":{\"message\":\"Data to send to target.\",\"target\":\"Contract on Zora that will receive message.\"}},\"relayTokens(address,address,uint256,address)\":{\"params\":{\"amount\":\"Amount of L1 tokens to deposit and L2 tokens to receive.\",\"l1Token\":\"L1 token to deposit.\",\"l2Token\":\"L2 token to receive.\",\"to\":\"Bridge recipient.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":{\"notice\":\"Constructs new Adapter.\"},\"relayMessage(address,bytes)\":{\"notice\":\"Send cross-chain message to target on Zora.\"},\"relayTokens(address,address,uint256,address)\":{\"notice\":\"Bridge tokens to Zora.\"}},\"notice\":\"Contract containing logic to send messages from L1 to Zora. This is a clone of the Base/Mode adapter\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/chain-adapters/Zora_Adapter.sol\":\"Zora_Adapter\"},\"debug\":{\"revertStrings\":\"strip\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@eth-optimism/contracts/L1/messaging/IL1ERC20Bridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >0.5.0 <0.9.0;\\n\\n/**\\n * @title IL1ERC20Bridge\\n */\\ninterface IL1ERC20Bridge {\\n /**********\\n * Events *\\n **********/\\n\\n event ERC20DepositInitiated(\\n address indexed _l1Token,\\n address indexed _l2Token,\\n address indexed _from,\\n address _to,\\n uint256 _amount,\\n bytes _data\\n );\\n\\n event ERC20WithdrawalFinalized(\\n address indexed _l1Token,\\n address indexed _l2Token,\\n address indexed _from,\\n address _to,\\n uint256 _amount,\\n bytes _data\\n );\\n\\n /********************\\n * Public Functions *\\n ********************/\\n\\n /**\\n * @dev get the address of the corresponding L2 bridge contract.\\n * @return Address of the corresponding L2 bridge contract.\\n */\\n function l2TokenBridge() external returns (address);\\n\\n /**\\n * @dev deposit an amount of the ERC20 to the caller's balance on L2.\\n * @param _l1Token Address of the L1 ERC20 we are depositing\\n * @param _l2Token Address of the L1 respective L2 ERC20\\n * @param _amount Amount of the ERC20 to deposit\\n * @param _l2Gas Gas limit required to complete the deposit on L2.\\n * @param _data Optional data to forward to L2. This data is provided\\n * solely as a convenience for external contracts. Aside from enforcing a maximum\\n * length, these contracts provide no guarantees about its content.\\n */\\n function depositERC20(\\n address _l1Token,\\n address _l2Token,\\n uint256 _amount,\\n uint32 _l2Gas,\\n bytes calldata _data\\n ) external;\\n\\n /**\\n * @dev deposit an amount of ERC20 to a recipient's balance on L2.\\n * @param _l1Token Address of the L1 ERC20 we are depositing\\n * @param _l2Token Address of the L1 respective L2 ERC20\\n * @param _to L2 address to credit the withdrawal to.\\n * @param _amount Amount of the ERC20 to deposit.\\n * @param _l2Gas Gas limit required to complete the deposit on L2.\\n * @param _data Optional data to forward to L2. This data is provided\\n * solely as a convenience for external contracts. Aside from enforcing a maximum\\n * length, these contracts provide no guarantees about its content.\\n */\\n function depositERC20To(\\n address _l1Token,\\n address _l2Token,\\n address _to,\\n uint256 _amount,\\n uint32 _l2Gas,\\n bytes calldata _data\\n ) external;\\n\\n /*************************\\n * Cross-chain Functions *\\n *************************/\\n\\n /**\\n * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\\n * L1 ERC20 token.\\n * This call will fail if the initialized withdrawal from L2 has not been finalized.\\n *\\n * @param _l1Token Address of L1 token to finalizeWithdrawal for.\\n * @param _l2Token Address of L2 token where withdrawal was initiated.\\n * @param _from L2 address initiating the transfer.\\n * @param _to L1 address to credit the withdrawal to.\\n * @param _amount Amount of the ERC20 to deposit.\\n * @param _data Data provided by the sender on L2. This data is provided\\n * solely as a convenience for external contracts. Aside from enforcing a maximum\\n * length, these contracts provide no guarantees about its content.\\n */\\n function finalizeERC20Withdrawal(\\n address _l1Token,\\n address _l2Token,\\n address _from,\\n address _to,\\n uint256 _amount,\\n bytes calldata _data\\n ) external;\\n}\\n\",\"keccak256\":\"0x69f831896dcbb6bef4f2d6c8be6cd1bf352f5910074d3ce973b9f8e0a4f4c1dd\",\"license\":\"MIT\"},\"@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >0.5.0 <0.9.0;\\n\\nimport \\\"./IL1ERC20Bridge.sol\\\";\\n\\n/**\\n * @title IL1StandardBridge\\n */\\ninterface IL1StandardBridge is IL1ERC20Bridge {\\n /**********\\n * Events *\\n **********/\\n event ETHDepositInitiated(\\n address indexed _from,\\n address indexed _to,\\n uint256 _amount,\\n bytes _data\\n );\\n\\n event ETHWithdrawalFinalized(\\n address indexed _from,\\n address indexed _to,\\n uint256 _amount,\\n bytes _data\\n );\\n\\n /********************\\n * Public Functions *\\n ********************/\\n\\n /**\\n * @dev Deposit an amount of the ETH to the caller's balance on L2.\\n * @param _l2Gas Gas limit required to complete the deposit on L2.\\n * @param _data Optional data to forward to L2. This data is provided\\n * solely as a convenience for external contracts. Aside from enforcing a maximum\\n * length, these contracts provide no guarantees about its content.\\n */\\n function depositETH(uint32 _l2Gas, bytes calldata _data) external payable;\\n\\n /**\\n * @dev Deposit an amount of ETH to a recipient's balance on L2.\\n * @param _to L2 address to credit the withdrawal to.\\n * @param _l2Gas Gas limit required to complete the deposit on L2.\\n * @param _data Optional data to forward to L2. This data is provided\\n * solely as a convenience for external contracts. Aside from enforcing a maximum\\n * length, these contracts provide no guarantees about its content.\\n */\\n function depositETHTo(\\n address _to,\\n uint32 _l2Gas,\\n bytes calldata _data\\n ) external payable;\\n\\n /*************************\\n * Cross-chain Functions *\\n *************************/\\n\\n /**\\n * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\\n * L1 ETH token. Since only the xDomainMessenger can call this function, it will never be called\\n * before the withdrawal is finalized.\\n * @param _from L2 address initiating the transfer.\\n * @param _to L1 address to credit the withdrawal to.\\n * @param _amount Amount of the ERC20 to deposit.\\n * @param _data Optional data to forward to L2. This data is provided\\n * solely as a convenience for external contracts. Aside from enforcing a maximum\\n * length, these contracts provide no guarantees about its content.\\n */\\n function finalizeETHWithdrawal(\\n address _from,\\n address _to,\\n uint256 _amount,\\n bytes calldata _data\\n ) external;\\n}\\n\",\"keccak256\":\"0x3d511f1bcea86aa88a9c41798926ea75b5b3f455c0377e63223a123a9e714ddc\",\"license\":\"MIT\"},\"@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity >0.5.0 <0.9.0;\\n\\n/**\\n * @title ICrossDomainMessenger\\n */\\ninterface ICrossDomainMessenger {\\n /**********\\n * Events *\\n **********/\\n\\n event SentMessage(\\n address indexed target,\\n address sender,\\n bytes message,\\n uint256 messageNonce,\\n uint256 gasLimit\\n );\\n event RelayedMessage(bytes32 indexed msgHash);\\n event FailedRelayedMessage(bytes32 indexed msgHash);\\n\\n /*************\\n * Variables *\\n *************/\\n\\n function xDomainMessageSender() external view returns (address);\\n\\n /********************\\n * Public Functions *\\n ********************/\\n\\n /**\\n * Sends a cross domain message to the target messenger.\\n * @param _target Target contract address.\\n * @param _message Message to send to the target.\\n * @param _gasLimit Gas limit for the provided message.\\n */\\n function sendMessage(\\n address _target,\\n bytes calldata _message,\\n uint32 _gasLimit\\n ) external;\\n}\\n\",\"keccak256\":\"0x8f29ae23021345a20ccac7b5edb3fc38268aef943b65adc8a32e74b80bf1833a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n *\\n * ==== Security Considerations\\n *\\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\\n * generally recommended is:\\n *\\n * ```solidity\\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\\n * doThing(..., value);\\n * }\\n *\\n * function doThing(..., uint256 value) public {\\n * token.safeTransferFrom(msg.sender, address(this), value);\\n * ...\\n * }\\n * ```\\n *\\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\\n * {SafeERC20-safeTransferFrom}).\\n *\\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\\n * contracts should have entry points that don't rely on permit.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n *\\n * CAUTION: See Security Considerations above.\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xb264c03a3442eb37a68ad620cefd1182766b58bee6cec40343480392d6b14d69\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n /**\\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n /**\\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\\n */\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful.\\n */\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\n }\\n }\\n\\n /**\\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\\n * to be set to zero before setting it to a non-zero value, such as USDT.\\n */\\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n *\\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\\n */\\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\\n // and not revert is the subcall reverts.\\n\\n (bool success, bytes memory returndata) = address(token).call(data);\\n return\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"contracts/chain-adapters/CrossDomainEnabled.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* Interface Imports */\\nimport { ICrossDomainMessenger } from \\\"@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol\\\";\\n\\n/**\\n * @title CrossDomainEnabled\\n * @custom:security-contact bugs@across.to\\n * @dev Helper contract for contracts performing cross-domain communications between L1 and Optimism.\\n * @dev This modifies the eth-optimism/CrossDomainEnabled contract only by changing state variables to be\\n * immutable for use in contracts like the Optimism_Adapter which use delegateCall().\\n */\\ncontract CrossDomainEnabled {\\n // Messenger contract used to send and recieve messages from the other domain.\\n address public immutable MESSENGER;\\n\\n /**\\n * @param _messenger Address of the CrossDomainMessenger on the current layer.\\n */\\n constructor(address _messenger) {\\n MESSENGER = _messenger;\\n }\\n\\n /**\\n * Gets the messenger, usually from storage. This function is exposed in case a child contract\\n * needs to override.\\n * @return The address of the cross-domain messenger contract which should be used.\\n */\\n function getCrossDomainMessenger() internal virtual returns (ICrossDomainMessenger) {\\n return ICrossDomainMessenger(MESSENGER);\\n }\\n\\n /**\\n * Sends a message to an account on another domain\\n * @param _crossDomainTarget The intended recipient on the destination domain\\n * @param _gasLimit The gasLimit for the receipt of the message on the target domain.\\n * @param _message The data to send to the target (usually calldata to a function with\\n * onlyFromCrossDomainAccount())\\n */\\n function sendCrossDomainMessage(\\n address _crossDomainTarget,\\n uint32 _gasLimit,\\n bytes calldata _message\\n ) internal {\\n // slither-disable-next-line reentrancy-events, reentrancy-benign\\n getCrossDomainMessenger().sendMessage(_crossDomainTarget, _message, _gasLimit);\\n }\\n}\\n\",\"keccak256\":\"0xb4705bab7468a6a7a6f3c635df73ca18215d5c78986dd336ab500fd75c63789f\",\"license\":\"MIT\"},\"contracts/chain-adapters/Zora_Adapter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\nimport \\\"./interfaces/AdapterInterface.sol\\\";\\nimport \\\"../external/interfaces/WETH9Interface.sol\\\";\\n\\n// @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need\\n// this contract's state variables to be `immutable` because of the delegateCall call.\\nimport \\\"./CrossDomainEnabled.sol\\\";\\nimport \\\"@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport \\\"../libraries/CircleCCTPAdapter.sol\\\";\\nimport \\\"../external/interfaces/CCTPInterfaces.sol\\\";\\n\\n/**\\n * @notice Contract containing logic to send messages from L1 to Zora. This is a clone of the Base/Mode adapter\\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\\n * that call this contract's logic guard against reentrancy.\\n * @custom:security-contact bugs@across.to\\n */\\n\\n// solhint-disable-next-line contract-name-camelcase\\ncontract Zora_Adapter is CrossDomainEnabled, AdapterInterface, CircleCCTPAdapter {\\n using SafeERC20 for IERC20;\\n uint32 public constant L2_GAS_LIMIT = 200_000;\\n\\n WETH9Interface public immutable L1_WETH;\\n\\n IL1StandardBridge public immutable L1_STANDARD_BRIDGE;\\n\\n /**\\n * @notice Constructs new Adapter.\\n * @param _l1Weth WETH address on L1.\\n * @param _crossDomainMessenger XDomainMessenger Zora system contract.\\n * @param _l1StandardBridge Standard bridge contract.\\n * @param _l1Usdc USDC address on L1.\\n */\\n constructor(\\n WETH9Interface _l1Weth,\\n address _crossDomainMessenger,\\n IL1StandardBridge _l1StandardBridge,\\n IERC20 _l1Usdc\\n )\\n CrossDomainEnabled(_crossDomainMessenger)\\n CircleCCTPAdapter(\\n _l1Usdc,\\n // Hardcode cctp messenger to 0x0 to disable CCTP bridging.\\n ITokenMessenger(address(0)),\\n CircleDomainIds.UNINTIALIZED\\n )\\n {\\n L1_WETH = _l1Weth;\\n L1_STANDARD_BRIDGE = _l1StandardBridge;\\n }\\n\\n /**\\n * @notice Send cross-chain message to target on Zora.\\n * @param target Contract on Zora that will receive message.\\n * @param message Data to send to target.\\n */\\n function relayMessage(address target, bytes calldata message) external payable override {\\n sendCrossDomainMessage(target, L2_GAS_LIMIT, message);\\n emit MessageRelayed(target, message);\\n }\\n\\n /**\\n * @notice Bridge tokens to Zora.\\n * @param l1Token L1 token to deposit.\\n * @param l2Token L2 token to receive.\\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\\n * @param to Bridge recipient.\\n */\\n function relayTokens(\\n address l1Token,\\n address l2Token,\\n uint256 amount,\\n address to\\n ) external payable override {\\n // If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.\\n if (l1Token == address(L1_WETH)) {\\n L1_WETH.withdraw(amount);\\n L1_STANDARD_BRIDGE.depositETHTo{ value: amount }(to, L2_GAS_LIMIT, \\\"\\\");\\n }\\n // Check if this token is USDC, which requires a custom bridge via CCTP.\\n else if (_isCCTPEnabled() && l1Token == address(usdcToken)) {\\n _transferUsdc(to, amount);\\n } else {\\n IL1StandardBridge _l1StandardBridge = L1_STANDARD_BRIDGE;\\n\\n IERC20(l1Token).safeIncreaseAllowance(address(_l1StandardBridge), amount);\\n _l1StandardBridge.depositERC20To(l1Token, l2Token, to, amount, L2_GAS_LIMIT, \\\"\\\");\\n }\\n emit TokensRelayed(l1Token, l2Token, amount, to);\\n }\\n}\\n\",\"keccak256\":\"0x9078778c59d070754d8f322474b88f8f153c7b22e0066c71b23fb13da4bcb38a\",\"license\":\"BUSL-1.1\"},\"contracts/chain-adapters/interfaces/AdapterInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\n/**\\n * @notice Sends cross chain messages and tokens to contracts on a specific L2 network.\\n * This interface is implemented by an adapter contract that is deployed on L1.\\n */\\n\\ninterface AdapterInterface {\\n event MessageRelayed(address target, bytes message);\\n\\n event TokensRelayed(address l1Token, address l2Token, uint256 amount, address to);\\n\\n /**\\n * @notice Send message to `target` on L2.\\n * @dev This method is marked payable because relaying the message might require a fee\\n * to be paid by the sender to forward the message to L2. However, it will not send msg.value\\n * to the target contract on L2.\\n * @param target L2 address to send message to.\\n * @param message Message to send to `target`.\\n */\\n function relayMessage(address target, bytes calldata message) external payable;\\n\\n /**\\n * @notice Send `amount` of `l1Token` to `to` on L2. `l2Token` is the L2 address equivalent of `l1Token`.\\n * @dev This method is marked payable because relaying the message might require a fee\\n * to be paid by the sender to forward the message to L2. However, it will not send msg.value\\n * to the target contract on L2.\\n * @param l1Token L1 token to bridge.\\n * @param l2Token L2 token to receive.\\n * @param amount Amount of `l1Token` to bridge.\\n * @param to Bridge recipient.\\n */\\n function relayTokens(\\n address l1Token,\\n address l2Token,\\n uint256 amount,\\n address to\\n ) external payable;\\n}\\n\",\"keccak256\":\"0x1d52fcb8b10dc7f260345918c1a90d496a4c9f774402cbd5ebde881b8fed6d50\",\"license\":\"BUSL-1.1\"},\"contracts/external/interfaces/CCTPInterfaces.sol\":{\"content\":\"/**\\n * Copyright (C) 2015, 2016, 2017 Dapphub\\n *\\n * This program is free software: you can redistribute it and/or modify\\n * it under the terms of the GNU General Public License as published by\\n * the Free Software Foundation, either version 3 of the License, or\\n * (at your option) any later version.\\n *\\n * This program is distributed in the hope that it will be useful,\\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\\n * GNU General Public License for more details.\\n *\\n * You should have received a copy of the GNU General Public License\\n * along with this program. If not, see .\\n */\\n\\n// SPDX-License-Identifier: GPL-3.0-or-later\\npragma solidity ^0.8.0;\\n\\n/**\\n * Imported as-is from commit 139d8d0ce3b5531d3c7ec284f89d946dfb720016 of:\\n * * https://github.com/walkerq/evm-cctp-contracts/blob/139d8d0ce3b5531d3c7ec284f89d946dfb720016/src/TokenMessenger.sol\\n * Changes applied post-import:\\n * * Removed a majority of code from this contract and converted the needed function signatures in this interface.\\n */\\ninterface ITokenMessenger {\\n /**\\n * @notice Deposits and burns tokens from sender to be minted on destination domain.\\n * Emits a `DepositForBurn` event.\\n * @dev reverts if:\\n * - given burnToken is not supported\\n * - given destinationDomain has no TokenMessenger registered\\n * - transferFrom() reverts. For example, if sender's burnToken balance or approved allowance\\n * to this contract is less than `amount`.\\n * - burn() reverts. For example, if `amount` is 0.\\n * - MessageTransmitter returns false or reverts.\\n * @param amount amount of tokens to burn\\n * @param destinationDomain destination domain\\n * @param mintRecipient address of mint recipient on destination domain\\n * @param burnToken address of contract to burn deposited tokens, on local domain\\n * @return _nonce unique nonce reserved by message\\n */\\n function depositForBurn(\\n uint256 amount,\\n uint32 destinationDomain,\\n bytes32 mintRecipient,\\n address burnToken\\n ) external returns (uint64 _nonce);\\n\\n /**\\n * @notice Minter responsible for minting and burning tokens on the local domain\\n * @dev A TokenMessenger stores a TokenMinter contract which extends the TokenController contract.\\n * https://github.com/circlefin/evm-cctp-contracts/blob/817397db0a12963accc08ff86065491577bbc0e5/src/TokenMessenger.sol#L110\\n * @return minter Token Minter contract.\\n */\\n function localMinter() external view returns (ITokenMinter minter);\\n}\\n\\n/**\\n * A TokenMessenger stores a TokenMinter contract which extends the TokenController contract. The TokenController\\n * contract has a burnLimitsPerMessage public mapping which can be queried to find the per-message burn limit\\n * for a given token:\\n * https://github.com/circlefin/evm-cctp-contracts/blob/817397db0a12963accc08ff86065491577bbc0e5/src/TokenMinter.sol#L33\\n * https://github.com/circlefin/evm-cctp-contracts/blob/817397db0a12963accc08ff86065491577bbc0e5/src/roles/TokenController.sol#L69C40-L69C60\\n *\\n */\\ninterface ITokenMinter {\\n /**\\n * @notice Supported burnable tokens on the local domain\\n * local token (address) => maximum burn amounts per message\\n * @param token address of token contract\\n * @return burnLimit maximum burn amount per message for token\\n */\\n function burnLimitsPerMessage(address token) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x9d6606bb3b0c52bcdbe834d4bc2cb97db6bfd2a906178598f5891d662d0450bd\",\"license\":\"GPL-3.0-or-later\"},\"contracts/external/interfaces/WETH9Interface.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\n/**\\n * @notice Interface for the WETH9 contract.\\n */\\ninterface WETH9Interface {\\n /**\\n * @notice Burn Wrapped Ether and receive native Ether.\\n * @param wad Amount of WETH to unwrap and send to caller.\\n */\\n function withdraw(uint256 wad) external;\\n\\n /**\\n * @notice Lock native Ether and mint Wrapped Ether ERC20\\n * @dev msg.value is amount of Wrapped Ether to mint/Ether to lock.\\n */\\n function deposit() external payable;\\n\\n /**\\n * @notice Get balance of WETH held by `guy`.\\n * @param guy Address to get balance of.\\n * @return wad Amount of WETH held by `guy`.\\n */\\n function balanceOf(address guy) external view returns (uint256 wad);\\n\\n /**\\n * @notice Transfer `wad` of WETH from caller to `guy`.\\n * @param guy Address to send WETH to.\\n * @param wad Amount of WETH to send.\\n * @return ok True if transfer succeeded.\\n */\\n function transfer(address guy, uint256 wad) external returns (bool);\\n}\\n\",\"keccak256\":\"0x3f7892554ec7f54681fdd3cc18a41346c246c9c1afba016c52990ef77741f718\",\"license\":\"BUSL-1.1\"},\"contracts/libraries/CircleCCTPAdapter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"../external/interfaces/CCTPInterfaces.sol\\\";\\n\\nlibrary CircleDomainIds {\\n uint32 public constant Ethereum = 0;\\n uint32 public constant Optimism = 2;\\n uint32 public constant Arbitrum = 3;\\n uint32 public constant Base = 6;\\n uint32 public constant Polygon = 7;\\n // Use this value for placeholder purposes only for adapters that extend this adapter but haven't yet been\\n // assigned a domain ID by Circle.\\n uint32 public constant UNINTIALIZED = type(uint32).max;\\n}\\n\\n/**\\n * @notice Facilitate bridging USDC via Circle's CCTP.\\n * @dev This contract is intended to be inherited by other chain-specific adapters and spoke pools.\\n * @custom:security-contact bugs@across.to\\n */\\nabstract contract CircleCCTPAdapter {\\n using SafeERC20 for IERC20;\\n\\n /**\\n * @notice The domain ID that CCTP will transfer funds to.\\n * @dev This identifier is assigned by Circle and is not related to a chain ID.\\n * @dev Official domain list can be found here: https://developers.circle.com/stablecoins/docs/supported-domains\\n */\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n uint32 public immutable recipientCircleDomainId;\\n\\n /**\\n * @notice The official USDC contract address on this chain.\\n * @dev Posted officially here: https://developers.circle.com/stablecoins/docs/usdc-on-main-networks\\n */\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n IERC20 public immutable usdcToken;\\n\\n /**\\n * @notice The official Circle CCTP token bridge contract endpoint.\\n * @dev Posted officially here: https://developers.circle.com/stablecoins/docs/evm-smart-contracts\\n */\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n ITokenMessenger public immutable cctpTokenMessenger;\\n\\n /**\\n * @notice intiailizes the CircleCCTPAdapter contract.\\n * @param _usdcToken USDC address on the current chain.\\n * @param _cctpTokenMessenger TokenMessenger contract to bridge via CCTP. If the zero address is passed, CCTP bridging will be disabled.\\n * @param _recipientCircleDomainId The domain ID that CCTP will transfer funds to.\\n */\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor(\\n IERC20 _usdcToken,\\n ITokenMessenger _cctpTokenMessenger,\\n uint32 _recipientCircleDomainId\\n ) {\\n usdcToken = _usdcToken;\\n cctpTokenMessenger = _cctpTokenMessenger;\\n recipientCircleDomainId = _recipientCircleDomainId;\\n }\\n\\n /**\\n * @notice converts address to bytes32 (alignment preserving cast.)\\n * @param addr the address to convert to bytes32\\n * @dev Sourced from the official CCTP repo: https://github.com/walkerq/evm-cctp-contracts/blob/139d8d0ce3b5531d3c7ec284f89d946dfb720016/src/messages/Message.sol#L142C1-L148C6\\n */\\n function _addressToBytes32(address addr) internal pure returns (bytes32) {\\n return bytes32(uint256(uint160(addr)));\\n }\\n\\n /**\\n * @notice Returns whether or not the CCTP bridge is enabled.\\n * @dev If the CCTPTokenMessenger is the zero address, CCTP bridging is disabled.\\n */\\n function _isCCTPEnabled() internal view returns (bool) {\\n return address(cctpTokenMessenger) != address(0);\\n }\\n\\n /**\\n * @notice Transfers USDC from the current domain to the given address on the new domain.\\n * @dev This function will revert if the CCTP bridge is disabled. I.e. if the zero address is passed to the constructor for the cctpTokenMessenger.\\n * @param to Address to receive USDC on the new domain.\\n * @param amount Amount of USDC to transfer.\\n */\\n function _transferUsdc(address to, uint256 amount) internal {\\n // Only approve the exact amount to be transferred\\n usdcToken.safeIncreaseAllowance(address(cctpTokenMessenger), amount);\\n // Submit the amount to be transferred to bridged via the TokenMessenger.\\n // If the amount to send exceeds the burn limit per message, then split the message into smaller parts.\\n ITokenMinter cctpMinter = cctpTokenMessenger.localMinter();\\n uint256 burnLimit = cctpMinter.burnLimitsPerMessage(address(usdcToken));\\n uint256 remainingAmount = amount;\\n bytes32 recipient = _addressToBytes32(to);\\n while (remainingAmount > 0) {\\n uint256 partAmount = remainingAmount > burnLimit ? burnLimit : remainingAmount;\\n cctpTokenMessenger.depositForBurn(partAmount, recipientCircleDomainId, recipient, address(usdcToken));\\n remainingAmount -= partAmount;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x04481a0fe0c4a39c047d485a1f7563b737417fadb6cb42ceb4d0b286493d8124\",\"license\":\"BUSL-1.1\"}},\"version\":1}", + "bytecode": "0x6101403461012a57601f61120c38819003918201601f19168301916001600160401b0383118484101761012e5780849260809460405283398101031261012a578051906001600160a01b03808316830361012a576020820151818116810361012a57604083015192828416840361012a5760600151918216820361012a5760805260c0525f60e05263ffffffff60a052610100918252610120908152604051906110c99283610143843960805183818161010901526102be015260a05183818161031d0152610751015260c05183818161061a01528181610b750152610cd6015260e05183818161024f015281816105eb01528181610656015281816106bf01526108570152518281816104090152610c6a0152518181816104ab015281816109c60152610bfc0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080806040526004361015610012575f80fd5b5f905f3560e01c90816311eac85514610c8e575080631efd482a14610c2057806335a2db6a14610bb257806352c8c75c1461037d5780635e743ef7146103415780636e400983146102e2578063927ede2d146102735780639748cf7c146102045763e6eb8ade14610081575f80fd5b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610201576100b3610cfa565b6024359067ffffffffffffffff908183116101ee57366023840112156101ee5782600401359182116101ee57602483019260248336920101116101ee578373ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001692833b156101fd5782906040519283917f3dbb202b00000000000000000000000000000000000000000000000000000000835216948560048301526060602483015281838161017c606482018b8d610d9f565b62030d40604483015203925af180156101f2576101da575b50506101d47f9e6c52944e331ba6270e7fe4cea2a4086bae8f7a27e1cdba07f416806f5d0ac4936040519384938452604060208501526040840191610d9f565b0390a180f35b6101e390610d1d565b6101ee57835f610194565b8380fd5b6040513d84823e3d90fd5b8280fd5b80fd5b503461020157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020157602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461020157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020157602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461020157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020157602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461020157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020157602060405162030d408152f35b5060807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610944576103b0610cfa565b60243573ffffffffffffffffffffffffffffffffffffffff81168103610944576064359073ffffffffffffffffffffffffffffffffffffffff82168203610944578373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168073ffffffffffffffffffffffffffffffffffffffff8616145f146105d257803b156105ba578180916024604051809481937f2e1a7d4d00000000000000000000000000000000000000000000000000000000835260443560048401525af180156101f2576105be575b5073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016803b156105ba5781608491604051928380927f9a2ac6d500000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff8916600483015262030d40602483015260606044830152846064830152604435905af180156101f2576105a2575b50509173ffffffffffffffffffffffffffffffffffffffff608092817fd7e09655439c3932e55857df3220186e5a7f0980825f20691c2b35d941dee75b955b81604051951685521660208401526044356040840152166060820152a180f35b6105ae90949294610d1d565b6101ee5791835f610543565b5080fd5b6105c790610d1d565b6101ee57835f610493565b505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016151580610b5d575b156109af577f000000000000000000000000000000000000000000000000000000000000000061067c60443573ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001683610ddd565b6040517fcb75c11c00000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561095057869161095b575b50602073ffffffffffffffffffffffffffffffffffffffff916024604051809481937fa56ec6320000000000000000000000000000000000000000000000000000000083528188166004840152165afa90811561095057869161091a575b50907f000000000000000000000000000000000000000000000000000000000000000063ffffffff1690604435805b6107c557505050509173ffffffffffffffffffffffffffffffffffffffff608092817fd7e09655439c3932e55857df3220186e5a7f0980825f20691c2b35d941dee75b95610582565b8381111561091457835b6040517f6fd3504e00000000000000000000000000000000000000000000000000000000815281600482015284602482015273ffffffffffffffffffffffffffffffffffffffff8816604482015273ffffffffffffffffffffffffffffffffffffffff841660648201526020816084818d73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af18015610909576108c1575b508103908111610894578061077c565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6020813d602011610901575b816108da60209383610d5e565b810103126108fd575167ffffffffffffffff8116036108f9575f610884565b8880fd5b8980fd5b3d91506108cd565b6040513d8c823e3d90fd5b806107cf565b90506020813d602011610948575b8161093560209383610d5e565b8101031261094457515f61074d565b5f80fd5b3d9150610928565b6040513d88823e3d90fd5b90506020813d6020116109a7575b8161097660209383610d5e565b810103126109a3575173ffffffffffffffffffffffffffffffffffffffff811681036109a35760206106ef565b8580fd5b3d9150610969565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016610a096044358273ffffffffffffffffffffffffffffffffffffffff8716610ddd565b803b15610944575f809160e4604051809481937f838b252000000000000000000000000000000000000000000000000000000000835273ffffffffffffffffffffffffffffffffffffffff8a16600484015273ffffffffffffffffffffffffffffffffffffffff8816602484015273ffffffffffffffffffffffffffffffffffffffff89166044840152604435606484015262030d40608484015260c060a48401528160c48401525af18015610b5257610b00575b509173ffffffffffffffffffffffffffffffffffffffff608092817fd7e09655439c3932e55857df3220186e5a7f0980825f20691c2b35d941dee75b95610582565b7fd7e09655439c3932e55857df3220186e5a7f0980825f20691c2b35d941dee75b93919450608092610b4673ffffffffffffffffffffffffffffffffffffffff92610d1d565b5f959294509250610abe565b6040513d5f823e3d90fd5b5073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841614610613565b34610944575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261094457602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610944575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261094457602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610944575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109445760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361094457565b67ffffffffffffffff8111610d3157604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610d3157604052565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b9291909273ffffffffffffffffffffffffffffffffffffffff809116604051917fdd62ed3e000000000000000000000000000000000000000000000000000000008352306004840152602495169182868201526020938482604481865afa918215610b52575f9261103b575b50810180911161100f5760405190848201937f095ea7b3000000000000000000000000000000000000000000000000000000008552878301526044820152604481526080810167ffffffffffffffff9382821085831117610fe35760c083019282841086851117610fb757865f94938594604052527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656460a0820152519082855af1903d15610fa6573d928311610f7a57610f429394955060405192610f35867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160185610d5e565b83523d5f8685013e61106a565b8051918215918215610f5a575b505090501561094457565b809250819381010312610944570151801515810361094457805f80610f4f565b857f4e487b71000000000000000000000000000000000000000000000000000000005f5260416004525ffd5b9150610f429293945060609161106a565b887f4e487b71000000000000000000000000000000000000000000000000000000005f5260416004525ffd5b877f4e487b71000000000000000000000000000000000000000000000000000000005f5260416004525ffd5b857f4e487b71000000000000000000000000000000000000000000000000000000005f5260116004525ffd5b9091508481813d8311611063575b6110538183610d5e565b810103126109445751905f610e49565b503d611049565b90156110845781511561107b575090565b3b156109445790565b50805190811561094457602001fdfea264697066735822122076c7bf3930f7b27088af43e78e2aabf88545f9737f1243b96495a446e748357f64736f6c63430008170033", + "deployedBytecode": "0x6080806040526004361015610012575f80fd5b5f905f3560e01c90816311eac85514610c8e575080631efd482a14610c2057806335a2db6a14610bb257806352c8c75c1461037d5780635e743ef7146103415780636e400983146102e2578063927ede2d146102735780639748cf7c146102045763e6eb8ade14610081575f80fd5b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610201576100b3610cfa565b6024359067ffffffffffffffff908183116101ee57366023840112156101ee5782600401359182116101ee57602483019260248336920101116101ee578373ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001692833b156101fd5782906040519283917f3dbb202b00000000000000000000000000000000000000000000000000000000835216948560048301526060602483015281838161017c606482018b8d610d9f565b62030d40604483015203925af180156101f2576101da575b50506101d47f9e6c52944e331ba6270e7fe4cea2a4086bae8f7a27e1cdba07f416806f5d0ac4936040519384938452604060208501526040840191610d9f565b0390a180f35b6101e390610d1d565b6101ee57835f610194565b8380fd5b6040513d84823e3d90fd5b8280fd5b80fd5b503461020157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020157602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461020157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020157602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461020157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020157602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b503461020157807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261020157602060405162030d408152f35b5060807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610944576103b0610cfa565b60243573ffffffffffffffffffffffffffffffffffffffff81168103610944576064359073ffffffffffffffffffffffffffffffffffffffff82168203610944578373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168073ffffffffffffffffffffffffffffffffffffffff8616145f146105d257803b156105ba578180916024604051809481937f2e1a7d4d00000000000000000000000000000000000000000000000000000000835260443560048401525af180156101f2576105be575b5073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016803b156105ba5781608491604051928380927f9a2ac6d500000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff8916600483015262030d40602483015260606044830152846064830152604435905af180156101f2576105a2575b50509173ffffffffffffffffffffffffffffffffffffffff608092817fd7e09655439c3932e55857df3220186e5a7f0980825f20691c2b35d941dee75b955b81604051951685521660208401526044356040840152166060820152a180f35b6105ae90949294610d1d565b6101ee5791835f610543565b5080fd5b6105c790610d1d565b6101ee57835f610493565b505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016151580610b5d575b156109af577f000000000000000000000000000000000000000000000000000000000000000061067c60443573ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001683610ddd565b6040517fcb75c11c00000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa90811561095057869161095b575b50602073ffffffffffffffffffffffffffffffffffffffff916024604051809481937fa56ec6320000000000000000000000000000000000000000000000000000000083528188166004840152165afa90811561095057869161091a575b50907f000000000000000000000000000000000000000000000000000000000000000063ffffffff1690604435805b6107c557505050509173ffffffffffffffffffffffffffffffffffffffff608092817fd7e09655439c3932e55857df3220186e5a7f0980825f20691c2b35d941dee75b95610582565b8381111561091457835b6040517f6fd3504e00000000000000000000000000000000000000000000000000000000815281600482015284602482015273ffffffffffffffffffffffffffffffffffffffff8816604482015273ffffffffffffffffffffffffffffffffffffffff841660648201526020816084818d73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165af18015610909576108c1575b508103908111610894578061077c565b6024887f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6020813d602011610901575b816108da60209383610d5e565b810103126108fd575167ffffffffffffffff8116036108f9575f610884565b8880fd5b8980fd5b3d91506108cd565b6040513d8c823e3d90fd5b806107cf565b90506020813d602011610948575b8161093560209383610d5e565b8101031261094457515f61074d565b5f80fd5b3d9150610928565b6040513d88823e3d90fd5b90506020813d6020116109a7575b8161097660209383610d5e565b810103126109a3575173ffffffffffffffffffffffffffffffffffffffff811681036109a35760206106ef565b8580fd5b3d9150610969565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016610a096044358273ffffffffffffffffffffffffffffffffffffffff8716610ddd565b803b15610944575f809160e4604051809481937f838b252000000000000000000000000000000000000000000000000000000000835273ffffffffffffffffffffffffffffffffffffffff8a16600484015273ffffffffffffffffffffffffffffffffffffffff8816602484015273ffffffffffffffffffffffffffffffffffffffff89166044840152604435606484015262030d40608484015260c060a48401528160c48401525af18015610b5257610b00575b509173ffffffffffffffffffffffffffffffffffffffff608092817fd7e09655439c3932e55857df3220186e5a7f0980825f20691c2b35d941dee75b95610582565b7fd7e09655439c3932e55857df3220186e5a7f0980825f20691c2b35d941dee75b93919450608092610b4673ffffffffffffffffffffffffffffffffffffffff92610d1d565b5f959294509250610abe565b6040513d5f823e3d90fd5b5073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff841614610613565b34610944575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261094457602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610944575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261094457602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610944575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126109445760209073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361094457565b67ffffffffffffffff8111610d3157604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610d3157604052565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b9291909273ffffffffffffffffffffffffffffffffffffffff809116604051917fdd62ed3e000000000000000000000000000000000000000000000000000000008352306004840152602495169182868201526020938482604481865afa918215610b52575f9261103b575b50810180911161100f5760405190848201937f095ea7b3000000000000000000000000000000000000000000000000000000008552878301526044820152604481526080810167ffffffffffffffff9382821085831117610fe35760c083019282841086851117610fb757865f94938594604052527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656460a0820152519082855af1903d15610fa6573d928311610f7a57610f429394955060405192610f35867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160185610d5e565b83523d5f8685013e61106a565b8051918215918215610f5a575b505090501561094457565b809250819381010312610944570151801515810361094457805f80610f4f565b857f4e487b71000000000000000000000000000000000000000000000000000000005f5260416004525ffd5b9150610f429293945060609161106a565b887f4e487b71000000000000000000000000000000000000000000000000000000005f5260416004525ffd5b877f4e487b71000000000000000000000000000000000000000000000000000000005f5260416004525ffd5b857f4e487b71000000000000000000000000000000000000000000000000000000005f5260116004525ffd5b9091508481813d8311611063575b6110538183610d5e565b810103126109445751905f610e49565b503d611049565b90156110845781511561107b575090565b3b156109445790565b50805190811561094457602001fdfea264697066735822122076c7bf3930f7b27088af43e78e2aabf88545f9737f1243b96495a446e748357f64736f6c63430008170033", + "devdoc": { + "custom:security-contact": "bugs@across.to", + "details": "Public functions calling external contracts do not guard against reentrancy because they are expected to be called via delegatecall, which will execute this contract's logic within the context of the originating contract. For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods that call this contract's logic guard against reentrancy.", + "kind": "dev", + "methods": { + "constructor": { + "params": { + "_crossDomainMessenger": "XDomainMessenger Zora system contract.", + "_l1StandardBridge": "Standard bridge contract.", + "_l1Usdc": "USDC address on L1.", + "_l1Weth": "WETH address on L1." + } + }, + "relayMessage(address,bytes)": { + "params": { + "message": "Data to send to target.", + "target": "Contract on Zora that will receive message." + } + }, + "relayTokens(address,address,uint256,address)": { + "params": { + "amount": "Amount of L1 tokens to deposit and L2 tokens to receive.", + "l1Token": "L1 token to deposit.", + "l2Token": "L2 token to receive.", + "to": "Bridge recipient." + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "constructor": { + "notice": "Constructs new Adapter." + }, + "relayMessage(address,bytes)": { + "notice": "Send cross-chain message to target on Zora." + }, + "relayTokens(address,address,uint256,address)": { + "notice": "Bridge tokens to Zora." + } + }, + "notice": "Contract containing logic to send messages from L1 to Zora. This is a clone of the Base/Mode adapter", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/mainnet/solcInputs/8c8d8b75dd96f63e54bfa124522c7f29.json b/deployments/mainnet/solcInputs/8c8d8b75dd96f63e54bfa124522c7f29.json new file mode 100644 index 000000000..49003c432 --- /dev/null +++ b/deployments/mainnet/solcInputs/8c8d8b75dd96f63e54bfa124522c7f29.json @@ -0,0 +1,556 @@ +{ + "language": "Solidity", + "sources": { + "@eth-optimism/contracts/L1/messaging/IL1ERC20Bridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/**\n * @title IL1ERC20Bridge\n */\ninterface IL1ERC20Bridge {\n /**********\n * Events *\n **********/\n\n event ERC20DepositInitiated(\n address indexed _l1Token,\n address indexed _l2Token,\n address indexed _from,\n address _to,\n uint256 _amount,\n bytes _data\n );\n\n event ERC20WithdrawalFinalized(\n address indexed _l1Token,\n address indexed _l2Token,\n address indexed _from,\n address _to,\n uint256 _amount,\n bytes _data\n );\n\n /********************\n * Public Functions *\n ********************/\n\n /**\n * @dev get the address of the corresponding L2 bridge contract.\n * @return Address of the corresponding L2 bridge contract.\n */\n function l2TokenBridge() external returns (address);\n\n /**\n * @dev deposit an amount of the ERC20 to the caller's balance on L2.\n * @param _l1Token Address of the L1 ERC20 we are depositing\n * @param _l2Token Address of the L1 respective L2 ERC20\n * @param _amount Amount of the ERC20 to deposit\n * @param _l2Gas Gas limit required to complete the deposit on L2.\n * @param _data Optional data to forward to L2. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function depositERC20(\n address _l1Token,\n address _l2Token,\n uint256 _amount,\n uint32 _l2Gas,\n bytes calldata _data\n ) external;\n\n /**\n * @dev deposit an amount of ERC20 to a recipient's balance on L2.\n * @param _l1Token Address of the L1 ERC20 we are depositing\n * @param _l2Token Address of the L1 respective L2 ERC20\n * @param _to L2 address to credit the withdrawal to.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _l2Gas Gas limit required to complete the deposit on L2.\n * @param _data Optional data to forward to L2. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function depositERC20To(\n address _l1Token,\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _l2Gas,\n bytes calldata _data\n ) external;\n\n /*************************\n * Cross-chain Functions *\n *************************/\n\n /**\n * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\n * L1 ERC20 token.\n * This call will fail if the initialized withdrawal from L2 has not been finalized.\n *\n * @param _l1Token Address of L1 token to finalizeWithdrawal for.\n * @param _l2Token Address of L2 token where withdrawal was initiated.\n * @param _from L2 address initiating the transfer.\n * @param _to L1 address to credit the withdrawal to.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _data Data provided by the sender on L2. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function finalizeERC20Withdrawal(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external;\n}\n" + }, + "@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\nimport \"./IL1ERC20Bridge.sol\";\n\n/**\n * @title IL1StandardBridge\n */\ninterface IL1StandardBridge is IL1ERC20Bridge {\n /**********\n * Events *\n **********/\n event ETHDepositInitiated(\n address indexed _from,\n address indexed _to,\n uint256 _amount,\n bytes _data\n );\n\n event ETHWithdrawalFinalized(\n address indexed _from,\n address indexed _to,\n uint256 _amount,\n bytes _data\n );\n\n /********************\n * Public Functions *\n ********************/\n\n /**\n * @dev Deposit an amount of the ETH to the caller's balance on L2.\n * @param _l2Gas Gas limit required to complete the deposit on L2.\n * @param _data Optional data to forward to L2. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function depositETH(uint32 _l2Gas, bytes calldata _data) external payable;\n\n /**\n * @dev Deposit an amount of ETH to a recipient's balance on L2.\n * @param _to L2 address to credit the withdrawal to.\n * @param _l2Gas Gas limit required to complete the deposit on L2.\n * @param _data Optional data to forward to L2. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function depositETHTo(\n address _to,\n uint32 _l2Gas,\n bytes calldata _data\n ) external payable;\n\n /*************************\n * Cross-chain Functions *\n *************************/\n\n /**\n * @dev Complete a withdrawal from L2 to L1, and credit funds to the recipient's balance of the\n * L1 ETH token. Since only the xDomainMessenger can call this function, it will never be called\n * before the withdrawal is finalized.\n * @param _from L2 address initiating the transfer.\n * @param _to L1 address to credit the withdrawal to.\n * @param _amount Amount of the ERC20 to deposit.\n * @param _data Optional data to forward to L2. This data is provided\n * solely as a convenience for external contracts. Aside from enforcing a maximum\n * length, these contracts provide no guarantees about its content.\n */\n function finalizeETHWithdrawal(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external;\n}\n" + }, + "@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >0.5.0 <0.9.0;\n\n/**\n * @title ICrossDomainMessenger\n */\ninterface ICrossDomainMessenger {\n /**********\n * Events *\n **********/\n\n event SentMessage(\n address indexed target,\n address sender,\n bytes message,\n uint256 messageNonce,\n uint256 gasLimit\n );\n event RelayedMessage(bytes32 indexed msgHash);\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n /*************\n * Variables *\n *************/\n\n function xDomainMessageSender() external view returns (address);\n\n /********************\n * Public Functions *\n ********************/\n\n /**\n * Sends a cross domain message to the target messenger.\n * @param _target Target contract address.\n * @param _message Message to send to the target.\n * @param _gasLimit Gas limit for the provided message.\n */\n function sendMessage(\n address _target,\n bytes calldata _message,\n uint32 _gasLimit\n ) external;\n}\n" + }, + "@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\n/**\n * @title Lib_PredeployAddresses\n */\nlibrary Lib_PredeployAddresses {\n address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;\n address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;\n address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;\n address payable internal constant OVM_ETH = payable(0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000);\n address internal constant L2_CROSS_DOMAIN_MESSENGER =\n 0x4200000000000000000000000000000000000007;\n address internal constant LIB_ADDRESS_MANAGER = 0x4200000000000000000000000000000000000008;\n address internal constant PROXY_EOA = 0x4200000000000000000000000000000000000009;\n address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;\n address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;\n address internal constant L2_STANDARD_TOKEN_FACTORY =\n 0x4200000000000000000000000000000000000012;\n address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.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/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.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 OwnableUpgradeable is Initializable, ContextUpgradeable {\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 function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/crosschain/errorsUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (crosschain/errors.sol)\n\npragma solidity ^0.8.4;\n\nerror NotCrossChainCall();\nerror InvalidCrossChainSender(address actual, address expected);\n" + }, + "@openzeppelin/contracts-upgradeable/crosschain/optimism/LibOptimismUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (crosschain/optimism/LibOptimism.sol)\n\npragma solidity ^0.8.4;\n\nimport {ICrossDomainMessengerUpgradeable as Optimism_Bridge} from \"../../vendor/optimism/ICrossDomainMessengerUpgradeable.sol\";\nimport \"../errorsUpgradeable.sol\";\n\n/**\n * @dev Primitives for cross-chain aware contracts for https://www.optimism.io/[Optimism].\n * See the https://community.optimism.io/docs/developers/bridge/messaging/#accessing-msg-sender[documentation]\n * for the functionality used here.\n */\nlibrary LibOptimismUpgradeable {\n /**\n * @dev Returns whether the current function call is the result of a\n * cross-chain message relayed by `messenger`.\n */\n function isCrossChain(address messenger) internal view returns (bool) {\n return msg.sender == messenger;\n }\n\n /**\n * @dev Returns the address of the sender that triggered the current\n * cross-chain message through `messenger`.\n *\n * NOTE: {isCrossChain} should be checked before trying to recover the\n * sender, as it will revert with `NotCrossChainCall` if the current\n * function call is not the result of a cross-chain message.\n */\n function crossChainSender(address messenger) internal view returns (address) {\n if (!isCrossChain(messenger)) revert NotCrossChainCall();\n\n return Optimism_Bridge(messenger).xDomainMessageSender();\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822ProxiableUpgradeable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.8.3._\n */\ninterface IERC1967Upgradeable {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeaconUpgradeable {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeaconUpgradeable.sol\";\nimport \"../../interfaces/IERC1967Upgradeable.sol\";\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/StorageSlotUpgradeable.sol\";\nimport {Initializable} from \"../utils/Initializable.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n */\nabstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n function __ERC1967Upgrade_init() internal onlyInitializing {\n }\n\n function __ERC1967Upgrade_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(AddressUpgradeable.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n AddressUpgradeable.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(AddressUpgradeable.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);\n }\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../ERC1967/ERC1967UpgradeUpgradeable.sol\";\nimport {Initializable} from \"./Initializable.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n address private immutable __self = address(this);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n require(address(this) != __self, \"Function must be called through delegatecall\");\n require(_getImplementation() == __self, \"Function must be called through active proxy\");\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n _;\n }\n\n function __UUPSUpgradeable_init() internal onlyInitializing {\n }\n\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n return _IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeTo(address newImplementation) public virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n *\n * @custom:oz-upgrades-unsafe-allow-reachable delegatecall\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data, true);\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal override onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../StringsUpgradeable.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", StringsUpgradeable.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary MathUpgradeable {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMathUpgradeable {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlotUpgradeable {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/MathUpgradeable.sol\";\nimport \"./math/SignedMathUpgradeable.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = MathUpgradeable.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMathUpgradeable.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, MathUpgradeable.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/vendor/optimism/ICrossDomainMessengerUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (vendor/optimism/ICrossDomainMessenger.sol)\npragma solidity >0.5.0 <0.9.0;\n\n/**\n * @title ICrossDomainMessenger\n */\ninterface ICrossDomainMessengerUpgradeable {\n /**********\n * Events *\n **********/\n\n event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit);\n event RelayedMessage(bytes32 indexed msgHash);\n event FailedRelayedMessage(bytes32 indexed msgHash);\n\n /*************\n * Variables *\n *************/\n\n function xDomainMessageSender() external view returns (address);\n\n /********************\n * Public Functions *\n ********************/\n\n /**\n * Sends a cross domain message to the target messenger.\n * @param _target Target contract address.\n * @param _message Message to send to the target.\n * @param _gasLimit Gas limit for the provided message.\n */\n function sendMessage(address _target, bytes calldata _message, uint32 _gasLimit) external;\n}\n" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(account),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n *\n * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@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/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC1271.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC1271 standard signature validation method for\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\n *\n * _Available since v4.1._\n */\ninterface IERC1271 {\n /**\n * @dev Should return whether the signature provided is valid for the provided data\n * @param hash Hash of the data to be signed\n * @param signature Signature byte array associated with _data\n */\n function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC1967.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.8.3._\n */\ninterface IERC1967 {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/beacon/BeaconProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../Proxy.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements a proxy that gets the implementation address for each call from an {UpgradeableBeacon}.\n *\n * The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't\n * conflict with the storage layout of the implementation behind the proxy.\n *\n * _Available since v3.4._\n */\ncontract BeaconProxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the proxy with `beacon`.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This\n * will typically be an encoded function call, and allows initializing the storage of the proxy like a Solidity\n * constructor.\n *\n * Requirements:\n *\n * - `beacon` must be a contract with the interface {IBeacon}.\n */\n constructor(address beacon, bytes memory data) payable {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n\n /**\n * @dev Returns the current beacon address.\n */\n function _beacon() internal view virtual returns (address) {\n return _getBeacon();\n }\n\n /**\n * @dev Returns the current implementation address of the associated beacon.\n */\n function _implementation() internal view virtual override returns (address) {\n return IBeacon(_getBeacon()).implementation();\n }\n\n /**\n * @dev Changes the proxy to use a new beacon. Deprecated: see {_upgradeBeaconToAndCall}.\n *\n * If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon.\n *\n * Requirements:\n *\n * - `beacon` must be a contract.\n * - The implementation returned by `beacon` must be a contract.\n */\n function _setBeacon(address beacon, bytes memory data) internal virtual {\n _upgradeBeaconToAndCall(beacon, data, false);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IBeacon.sol\";\nimport \"../../access/Ownable.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their\n * implementation contract, which is where they will delegate all function calls.\n *\n * An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.\n */\ncontract UpgradeableBeacon is IBeacon, Ownable {\n address private _implementation;\n\n /**\n * @dev Emitted when the implementation returned by the beacon is changed.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the\n * beacon.\n */\n constructor(address implementation_) {\n _setImplementation(implementation_);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function implementation() public view virtual override returns (address) {\n return _implementation;\n }\n\n /**\n * @dev Upgrades the beacon to a new implementation.\n *\n * Emits an {Upgraded} event.\n *\n * Requirements:\n *\n * - msg.sender must be the owner of the contract.\n * - `newImplementation` must be a contract.\n */\n function upgradeTo(address newImplementation) public virtual onlyOwner {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Sets the implementation contract address for this beacon\n *\n * Requirements:\n *\n * - `newImplementation` must be a contract.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"UpgradeableBeacon: implementation is not a contract\");\n _implementation = newImplementation;\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializing the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n _upgradeToAndCall(_logic, _data, false);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n return ERC1967Upgrade._getImplementation();\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/IERC1967.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n */\nabstract contract ERC1967Upgrade is IERC1967 {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overridden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.3) (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./TransparentUpgradeableProxy.sol\";\nimport \"../../access/Ownable.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n /**\n * @dev Returns the current implementation of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyImplementation(ITransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Returns the current admin of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyAdmin(ITransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `proxy` to `newAdmin`.\n *\n * Requirements:\n *\n * - This contract must be the current admin of `proxy`.\n */\n function changeProxyAdmin(ITransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n proxy.changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgrade(ITransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n proxy.upgradeTo(implementation);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgradeAndCall(\n ITransparentUpgradeableProxy proxy,\n address implementation,\n bytes memory data\n ) public payable virtual onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy}\n * does not implement this interface directly, and some of its functions are implemented by an internal dispatch\n * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not\n * include them in the ABI so this interface must be used to interact with it.\n */\ninterface ITransparentUpgradeableProxy is IERC1967 {\n function admin() external view returns (address);\n\n function implementation() external view returns (address);\n\n function changeAdmin(address) external;\n\n function upgradeTo(address) external;\n\n function upgradeToAndCall(address, bytes memory) external payable;\n}\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n *\n * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not\n * inherit from that interface, and instead the admin functions are implicitly implemented using a custom dispatch\n * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to\n * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the\n * implementation.\n *\n * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the compiler\n * will not check that there are no selector conflicts, due to the note above. A selector clash between any new function\n * and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This could\n * render the admin operations inaccessible, which could prevent upgradeability. Transparency may also be compromised.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(address _logic, address admin_, bytes memory _data) payable ERC1967Proxy(_logic, _data) {\n _changeAdmin(admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n *\n * CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the\n * implementation provides a function with the same selector.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior\n */\n function _fallback() internal virtual override {\n if (msg.sender == _getAdmin()) {\n bytes memory ret;\n bytes4 selector = msg.sig;\n if (selector == ITransparentUpgradeableProxy.upgradeTo.selector) {\n ret = _dispatchUpgradeTo();\n } else if (selector == ITransparentUpgradeableProxy.upgradeToAndCall.selector) {\n ret = _dispatchUpgradeToAndCall();\n } else if (selector == ITransparentUpgradeableProxy.changeAdmin.selector) {\n ret = _dispatchChangeAdmin();\n } else if (selector == ITransparentUpgradeableProxy.admin.selector) {\n ret = _dispatchAdmin();\n } else if (selector == ITransparentUpgradeableProxy.implementation.selector) {\n ret = _dispatchImplementation();\n } else {\n revert(\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n }\n assembly {\n return(add(ret, 0x20), mload(ret))\n }\n } else {\n super._fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function _dispatchAdmin() private returns (bytes memory) {\n _requireZeroValue();\n\n address admin = _getAdmin();\n return abi.encode(admin);\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function _dispatchImplementation() private returns (bytes memory) {\n _requireZeroValue();\n\n address implementation = _implementation();\n return abi.encode(implementation);\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _dispatchChangeAdmin() private returns (bytes memory) {\n _requireZeroValue();\n\n address newAdmin = abi.decode(msg.data[4:], (address));\n _changeAdmin(newAdmin);\n\n return \"\";\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n */\n function _dispatchUpgradeTo() private returns (bytes memory) {\n _requireZeroValue();\n\n address newImplementation = abi.decode(msg.data[4:], (address));\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n\n return \"\";\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n */\n function _dispatchUpgradeToAndCall() private returns (bytes memory) {\n (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes));\n _upgradeToAndCall(newImplementation, data, true);\n\n return \"\";\n }\n\n /**\n * @dev Returns the current admin.\n *\n * CAUTION: This function is deprecated. Use {ERC1967Upgrade-_getAdmin} instead.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to\n * emulate some proxy functions being non-payable while still allowing value to pass through.\n */\n function _requireZeroValue() private {\n require(msg.value == 0);\n }\n}\n" + }, + "@openzeppelin/contracts/security/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/ERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/ERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC1155.sol\";\nimport \"./IERC1155Receiver.sol\";\nimport \"./extensions/IERC1155MetadataURI.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the basic standard multi-token.\n * See https://eips.ethereum.org/EIPS/eip-1155\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\n *\n * _Available since v3.1._\n */\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\n using Address for address;\n\n // Mapping from token ID to account balances\n mapping(uint256 => mapping(address => uint256)) private _balances;\n\n // Mapping from account to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\n string private _uri;\n\n /**\n * @dev See {_setURI}.\n */\n constructor(string memory uri_) {\n _setURI(uri_);\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC1155).interfaceId ||\n interfaceId == type(IERC1155MetadataURI).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC1155MetadataURI-uri}.\n *\n * This implementation returns the same URI for *all* token types. It relies\n * on the token type ID substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * Clients calling this function must replace the `\\{id\\}` substring with the\n * actual token type ID.\n */\n function uri(uint256) public view virtual override returns (string memory) {\n return _uri;\n }\n\n /**\n * @dev See {IERC1155-balanceOf}.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\n require(account != address(0), \"ERC1155: address zero is not a valid owner\");\n return _balances[id][account];\n }\n\n /**\n * @dev See {IERC1155-balanceOfBatch}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(\n address[] memory accounts,\n uint256[] memory ids\n ) public view virtual override returns (uint256[] memory) {\n require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\n\n uint256[] memory batchBalances = new uint256[](accounts.length);\n\n for (uint256 i = 0; i < accounts.length; ++i) {\n batchBalances[i] = balanceOf(accounts[i], ids[i]);\n }\n\n return batchBalances;\n }\n\n /**\n * @dev See {IERC1155-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC1155-isApprovedForAll}.\n */\n function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[account][operator];\n }\n\n /**\n * @dev See {IERC1155-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner or approved\"\n );\n _safeTransferFrom(from, to, id, amount, data);\n }\n\n /**\n * @dev See {IERC1155-safeBatchTransferFrom}.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) public virtual override {\n require(\n from == _msgSender() || isApprovedForAll(from, _msgSender()),\n \"ERC1155: caller is not token owner or approved\"\n );\n _safeBatchTransferFrom(from, to, ids, amounts, data);\n }\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _safeTransferFrom(\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n\n emit TransferSingle(operator, from, to, id, amount);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _safeBatchTransferFrom(\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; ++i) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n _balances[id][to] += amount;\n }\n\n emit TransferBatch(operator, from, to, ids, amounts);\n\n _afterTokenTransfer(operator, from, to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\n }\n\n /**\n * @dev Sets a new URI for all token types, by relying on the token type ID\n * substitution mechanism\n * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n *\n * By this mechanism, any occurrence of the `\\{id\\}` substring in either the\n * URI or any of the amounts in the JSON file at said URI will be replaced by\n * clients with the token type ID.\n *\n * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be\n * interpreted by clients as\n * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\n * for token type ID 0x4cce0.\n *\n * See {uri}.\n *\n * Because these URIs cannot be meaningfully represented by the {URI} event,\n * this function emits no events.\n */\n function _setURI(string memory newuri) internal virtual {\n _uri = newuri;\n }\n\n /**\n * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function _mint(address to, uint256 id, uint256 amount, bytes memory data) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _balances[id][to] += amount;\n emit TransferSingle(operator, address(0), to, id, amount);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function _mintBatch(\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {\n require(to != address(0), \"ERC1155: mint to the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n for (uint256 i = 0; i < ids.length; i++) {\n _balances[ids[i]][to] += amounts[i];\n }\n\n emit TransferBatch(operator, address(0), to, ids, amounts);\n\n _afterTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\n }\n\n /**\n * @dev Destroys `amount` tokens of token type `id` from `from`\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `from` must have at least `amount` tokens of token type `id`.\n */\n function _burn(address from, uint256 id, uint256 amount) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n\n address operator = _msgSender();\n uint256[] memory ids = _asSingletonArray(id);\n uint256[] memory amounts = _asSingletonArray(amount);\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n\n emit TransferSingle(operator, from, address(0), id, amount);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n */\n function _burnBatch(address from, uint256[] memory ids, uint256[] memory amounts) internal virtual {\n require(from != address(0), \"ERC1155: burn from the zero address\");\n require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n address operator = _msgSender();\n\n _beforeTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n\n for (uint256 i = 0; i < ids.length; i++) {\n uint256 id = ids[i];\n uint256 amount = amounts[i];\n\n uint256 fromBalance = _balances[id][from];\n require(fromBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n unchecked {\n _balances[id][from] = fromBalance - amount;\n }\n }\n\n emit TransferBatch(operator, from, address(0), ids, amounts);\n\n _afterTokenTransfer(operator, from, address(0), ids, amounts, \"\");\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits an {ApprovalForAll} event.\n */\n function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\n require(owner != operator, \"ERC1155: setting approval status for self\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `ids` and `amounts` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any token transfer. This includes minting\n * and burning, as well as batched variants.\n *\n * The same hook is called on both single and batched variants. For single\n * transfers, the length of the `id` and `amount` arrays will be 1.\n *\n * Calling conditions (for each `id` and `amount` pair):\n *\n * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * of token type `id` will be transferred to `to`.\n * - When `from` is zero, `amount` tokens of token type `id` will be minted\n * for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n * will be burned.\n * - `from` and `to` are never both zero.\n * - `ids` and `amounts` have the same, non-zero length.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) internal virtual {}\n\n function _doSafeTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256 id,\n uint256 amount,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\n if (response != IERC1155Receiver.onERC1155Received.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non-ERC1155Receiver implementer\");\n }\n }\n }\n\n function _doSafeBatchTransferAcceptanceCheck(\n address operator,\n address from,\n address to,\n uint256[] memory ids,\n uint256[] memory amounts,\n bytes memory data\n ) private {\n if (to.isContract()) {\n try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\n bytes4 response\n ) {\n if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\n revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n }\n } catch Error(string memory reason) {\n revert(reason);\n } catch {\n revert(\"ERC1155: transfer to non-ERC1155Receiver implementer\");\n }\n }\n }\n\n function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\n uint256[] memory array = new uint256[](1);\n array[0] = element;\n\n return array;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155.sol\";\n\n/**\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155MetadataURI is IERC1155 {\n /**\n * @dev Returns the URI for token type `id`.\n *\n * If the `\\{id\\}` substring is present in the URI, it must be replaced by\n * clients with the actual token type ID.\n */\n function uri(uint256 id) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n /**\n * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n */\n event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n /**\n * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n * transfers.\n */\n event TransferBatch(\n address indexed operator,\n address indexed from,\n address indexed to,\n uint256[] ids,\n uint256[] values\n );\n\n /**\n * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n * `approved`.\n */\n event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n /**\n * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n *\n * If an {URI} event was emitted for `id`, the standard\n * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n * returned by {IERC1155MetadataURI-uri}.\n */\n event URI(string value, uint256 indexed id);\n\n /**\n * @dev Returns the amount of tokens of token type `id` owned by `account`.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function balanceOf(address account, uint256 id) external view returns (uint256);\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n *\n * Requirements:\n *\n * - `accounts` and `ids` must have the same length.\n */\n function balanceOfBatch(\n address[] calldata accounts,\n uint256[] calldata ids\n ) external view returns (uint256[] memory);\n\n /**\n * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n *\n * Emits an {ApprovalForAll} event.\n *\n * Requirements:\n *\n * - `operator` cannot be the caller.\n */\n function setApprovalForAll(address operator, bool approved) external;\n\n /**\n * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n *\n * See {setApprovalForAll}.\n */\n function isApprovedForAll(address account, address operator) external view returns (bool);\n\n /**\n * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n *\n * Emits a {TransferSingle} event.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n * - `from` must have a balance of tokens of type `id` of at least `amount`.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n * acceptance magic value.\n */\n function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;\n\n /**\n * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n *\n * Emits a {TransferBatch} event.\n *\n * Requirements:\n *\n * - `ids` and `amounts` must have the same length.\n * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n * acceptance magic value.\n */\n function safeBatchTransferFrom(\n address from,\n address to,\n uint256[] calldata ids,\n uint256[] calldata amounts,\n bytes calldata data\n ) external;\n}\n" + }, + "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n /**\n * @dev Handles the receipt of a single ERC1155 token type. This function is\n * called at the end of a `safeTransferFrom` after the balance has been updated.\n *\n * NOTE: To accept the transfer, this must return\n * `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n * (i.e. 0xf23a6e61, or its own function selector).\n *\n * @param operator The address which initiated the transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param id The ID of the token being transferred\n * @param value The amount of tokens being transferred\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n */\n function onERC1155Received(\n address operator,\n address from,\n uint256 id,\n uint256 value,\n bytes calldata data\n ) external returns (bytes4);\n\n /**\n * @dev Handles the receipt of a multiple ERC1155 token types. This function\n * is called at the end of a `safeBatchTransferFrom` after the balances have\n * been updated.\n *\n * NOTE: To accept the transfer(s), this must return\n * `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n * (i.e. 0xbc197c81, or its own function selector).\n *\n * @param operator The address which initiated the batch transfer (i.e. msg.sender)\n * @param from The address which previously owned the token\n * @param ids An array containing ids of each token being transferred (order and length must match values array)\n * @param values An array containing amounts of each token being transferred (order and length must match ids array)\n * @param data Additional data with no specified format\n * @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n */\n function onERC1155BatchReceived(\n address operator,\n address from,\n uint256[] calldata ids,\n uint256[] calldata values,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(address from, address to, uint256 amount) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n /**\n * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n /**\n * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n */\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\n * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n */\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n }\n }\n\n /**\n * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n * to be set to zero before setting it to a non-zero value, such as USDT.\n */\n function forceApprove(IERC20 token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n *\n * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n */\n function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n // and not revert is the subcall reverts.\n\n (bool success, bytes memory returndata) = address(token).call(data);\n return\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\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" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, \"\\x19Ethereum Signed Message:\\n32\")\n mstore(0x1c, hash)\n message := keccak256(0x00, 0x3c)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {\n /// @solidity memory-safe-assembly\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, \"\\x19\\x01\")\n mstore(add(ptr, 0x02), domainSeparator)\n mstore(add(ptr, 0x22), structHash)\n data := keccak256(ptr, 0x42)\n }\n }\n\n /**\n * @dev Returns an Ethereum Signed Data with intended validator, created from a\n * `validator` and `data` according to the version 0 of EIP-191.\n *\n * See {recover}.\n */\n function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x00\", validator, data));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProof(proof, leaf) == root;\n }\n\n /**\n * @dev Calldata version of {verify}\n *\n * _Available since v4.7._\n */\n function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n return processProofCalldata(proof, leaf) == root;\n }\n\n /**\n * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n * hash matches the root of the tree. When processing the proof, the pairs\n * of leafs & pre-images are assumed to be sorted.\n *\n * _Available since v4.4._\n */\n function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Calldata version of {processProof}\n *\n * _Available since v4.7._\n */\n function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {\n bytes32 computedHash = leaf;\n for (uint256 i = 0; i < proof.length; i++) {\n computedHash = _hashPair(computedHash, proof[i]);\n }\n return computedHash;\n }\n\n /**\n * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by\n * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerify(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProof(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Calldata version of {multiProofVerify}\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function multiProofVerifyCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32 root,\n bytes32[] memory leaves\n ) internal pure returns (bool) {\n return processMultiProofCalldata(proof, proofFlags, leaves) == root;\n }\n\n /**\n * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction\n * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another\n * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false\n * respectively.\n *\n * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree\n * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the\n * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).\n *\n * _Available since v4.7._\n */\n function processMultiProof(\n bytes32[] memory proof,\n bool[] memory proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 proofLen = proof.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proofLen - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n require(proofPos == proofLen, \"MerkleProof: invalid multiproof\");\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n /**\n * @dev Calldata version of {processMultiProof}.\n *\n * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.\n *\n * _Available since v4.7._\n */\n function processMultiProofCalldata(\n bytes32[] calldata proof,\n bool[] calldata proofFlags,\n bytes32[] memory leaves\n ) internal pure returns (bytes32 merkleRoot) {\n // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by\n // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the\n // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of\n // the merkle tree.\n uint256 leavesLen = leaves.length;\n uint256 proofLen = proof.length;\n uint256 totalHashes = proofFlags.length;\n\n // Check proof validity.\n require(leavesLen + proofLen - 1 == totalHashes, \"MerkleProof: invalid multiproof\");\n\n // The xxxPos values are \"pointers\" to the next value to consume in each array. All accesses are done using\n // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's \"pop\".\n bytes32[] memory hashes = new bytes32[](totalHashes);\n uint256 leafPos = 0;\n uint256 hashPos = 0;\n uint256 proofPos = 0;\n // At each step, we compute the next hash using two values:\n // - a value from the \"main queue\". If not all leaves have been consumed, we get the next leaf, otherwise we\n // get the next hash.\n // - depending on the flag, either another value from the \"main queue\" (merging branches) or an element from the\n // `proof` array.\n for (uint256 i = 0; i < totalHashes; i++) {\n bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];\n bytes32 b = proofFlags[i]\n ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])\n : proof[proofPos++];\n hashes[i] = _hashPair(a, b);\n }\n\n if (totalHashes > 0) {\n require(proofPos == proofLen, \"MerkleProof: invalid multiproof\");\n unchecked {\n return hashes[totalHashes - 1];\n }\n } else if (leavesLen > 0) {\n return leaves[0];\n } else {\n return proof[0];\n }\n }\n\n function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {\n return a < b ? _efficientHash(a, b) : _efficientHash(b, a);\n }\n\n function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, a)\n mstore(0x20, b)\n value := keccak256(0x00, 0x40)\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/SignatureChecker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\nimport \"../../interfaces/IERC1271.sol\";\n\n/**\n * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA\n * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like\n * Argent and Gnosis Safe.\n *\n * _Available since v4.1._\n */\nlibrary SignatureChecker {\n /**\n * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the\n * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.\n *\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\n */\n function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {\n (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);\n return\n (error == ECDSA.RecoverError.NoError && recovered == signer) ||\n isValidERC1271SignatureNow(signer, hash, signature);\n }\n\n /**\n * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated\n * against the signer smart contract using ERC1271.\n *\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\n */\n function isValidERC1271SignatureNow(\n address signer,\n bytes32 hash,\n bytes memory signature\n ) internal view returns (bool) {\n (bool success, bytes memory result) = signer.staticcall(\n abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)\n );\n return (success &&\n result.length >= 32 &&\n abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator.\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n unchecked {\n require(b <= a, errorMessage);\n return a - b;\n }\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a / b;\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a % b;\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SignedSafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/math/SignedSafeMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SignedSafeMath` is no longer needed starting with Solidity 0.8. The compiler\n * now has built in overflow checking.\n */\nlibrary SignedSafeMath {\n /**\n * @dev Returns the multiplication of two signed integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(int256 a, int256 b) internal pure returns (int256) {\n return a * b;\n }\n\n /**\n * @dev Returns the integer division of two signed integers. Reverts on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator.\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(int256 a, int256 b) internal pure returns (int256) {\n return a / b;\n }\n\n /**\n * @dev Returns the subtraction of two signed integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(int256 a, int256 b) internal pure returns (int256) {\n return a - b;\n }\n\n /**\n * @dev Returns the addition of two signed integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(int256 a, int256 b) internal pure returns (int256) {\n return a + b;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\n }\n}\n" + }, + "@scroll-tech/contracts/L1/gateways/IL1ERC20Gateway.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.16;\n\ninterface IL1ERC20Gateway {\n /**********\n * Events *\n **********/\n\n /// @notice Emitted when ERC20 token is withdrawn from L2 to L1 and transfer to recipient.\n /// @param l1Token The address of the token in L1.\n /// @param l2Token The address of the token in L2.\n /// @param from The address of sender in L2.\n /// @param to The address of recipient in L1.\n /// @param amount The amount of token withdrawn from L2 to L1.\n /// @param data The optional calldata passed to recipient in L1.\n event FinalizeWithdrawERC20(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n /// @notice Emitted when someone deposit ERC20 token from L1 to L2.\n /// @param l1Token The address of the token in L1.\n /// @param l2Token The address of the token in L2.\n /// @param from The address of sender in L1.\n /// @param to The address of recipient in L2.\n /// @param amount The amount of token will be deposited from L1 to L2.\n /// @param data The optional calldata passed to recipient in L2.\n event DepositERC20(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n /// @notice Emitted when some ERC20 token is refunded.\n /// @param token The address of the token in L1.\n /// @param recipient The address of receiver in L1.\n /// @param amount The amount of token refunded to receiver.\n event RefundERC20(address indexed token, address indexed recipient, uint256 amount);\n\n /*************************\n * Public View Functions *\n *************************/\n\n /// @notice Return the corresponding l2 token address given l1 token address.\n /// @param _l1Token The address of l1 token.\n function getL2ERC20Address(address _l1Token) external view returns (address);\n\n /*****************************\n * Public Mutating Functions *\n *****************************/\n\n /// @notice Deposit some token to a caller's account on L2.\n /// @dev Make this function payable to send relayer fee in Ether.\n /// @param _token The address of token in L1.\n /// @param _amount The amount of token to transfer.\n /// @param _gasLimit Gas limit required to complete the deposit on L2.\n function depositERC20(\n address _token,\n uint256 _amount,\n uint256 _gasLimit\n ) external payable;\n\n /// @notice Deposit some token to a recipient's account on L2.\n /// @dev Make this function payable to send relayer fee in Ether.\n /// @param _token The address of token in L1.\n /// @param _to The address of recipient's account on L2.\n /// @param _amount The amount of token to transfer.\n /// @param _gasLimit Gas limit required to complete the deposit on L2.\n function depositERC20(\n address _token,\n address _to,\n uint256 _amount,\n uint256 _gasLimit\n ) external payable;\n\n /// @notice Deposit some token to a recipient's account on L2 and call.\n /// @dev Make this function payable to send relayer fee in Ether.\n /// @param _token The address of token in L1.\n /// @param _to The address of recipient's account on L2.\n /// @param _amount The amount of token to transfer.\n /// @param _data Optional data to forward to recipient's account.\n /// @param _gasLimit Gas limit required to complete the deposit on L2.\n function depositERC20AndCall(\n address _token,\n address _to,\n uint256 _amount,\n bytes memory _data,\n uint256 _gasLimit\n ) external payable;\n\n /// @notice Complete ERC20 withdraw from L2 to L1 and send fund to recipient's account in L1.\n /// @dev Make this function payable to handle WETH deposit/withdraw.\n /// The function should only be called by L1ScrollMessenger.\n /// The function should also only be called by L2ERC20Gateway in L2.\n /// @param _l1Token The address of corresponding L1 token.\n /// @param _l2Token The address of corresponding L2 token.\n /// @param _from The address of account who withdraw the token in L2.\n /// @param _to The address of recipient in L1 to receive the token.\n /// @param _amount The amount of the token to withdraw.\n /// @param _data Optional data to forward to recipient's account.\n function finalizeWithdrawERC20(\n address _l1Token,\n address _l2Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable;\n}\n" + }, + "@scroll-tech/contracts/L1/gateways/IL1ETHGateway.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.16;\n\ninterface IL1ETHGateway {\n /**********\n * Events *\n **********/\n\n /// @notice Emitted when ETH is withdrawn from L2 to L1 and transfer to recipient.\n /// @param from The address of sender in L2.\n /// @param to The address of recipient in L1.\n /// @param amount The amount of ETH withdrawn from L2 to L1.\n /// @param data The optional calldata passed to recipient in L1.\n event FinalizeWithdrawETH(address indexed from, address indexed to, uint256 amount, bytes data);\n\n /// @notice Emitted when someone deposit ETH from L1 to L2.\n /// @param from The address of sender in L1.\n /// @param to The address of recipient in L2.\n /// @param amount The amount of ETH will be deposited from L1 to L2.\n /// @param data The optional calldata passed to recipient in L2.\n event DepositETH(address indexed from, address indexed to, uint256 amount, bytes data);\n\n /// @notice Emitted when some ETH is refunded.\n /// @param recipient The address of receiver in L1.\n /// @param amount The amount of ETH refunded to receiver.\n event RefundETH(address indexed recipient, uint256 amount);\n\n /*****************************\n * Public Mutating Functions *\n *****************************/\n\n /// @notice Deposit ETH to caller's account in L2.\n /// @param amount The amount of ETH to be deposited.\n /// @param gasLimit Gas limit required to complete the deposit on L2.\n function depositETH(uint256 amount, uint256 gasLimit) external payable;\n\n /// @notice Deposit ETH to some recipient's account in L2.\n /// @param to The address of recipient's account on L2.\n /// @param amount The amount of ETH to be deposited.\n /// @param gasLimit Gas limit required to complete the deposit on L2.\n function depositETH(\n address to,\n uint256 amount,\n uint256 gasLimit\n ) external payable;\n\n /// @notice Deposit ETH to some recipient's account in L2 and call the target contract.\n /// @param to The address of recipient's account on L2.\n /// @param amount The amount of ETH to be deposited.\n /// @param data Optional data to forward to recipient's account.\n /// @param gasLimit Gas limit required to complete the deposit on L2.\n function depositETHAndCall(\n address to,\n uint256 amount,\n bytes calldata data,\n uint256 gasLimit\n ) external payable;\n\n /// @notice Complete ETH withdraw from L2 to L1 and send fund to recipient's account in L1.\n /// @dev This function should only be called by L1ScrollMessenger.\n /// This function should also only be called by L1ETHGateway in L2.\n /// @param from The address of account who withdraw ETH in L2.\n /// @param to The address of recipient in L1 to receive ETH.\n /// @param amount The amount of ETH to withdraw.\n /// @param data Optional data to forward to recipient's account.\n function finalizeWithdrawETH(\n address from,\n address to,\n uint256 amount,\n bytes calldata data\n ) external payable;\n}\n" + }, + "@scroll-tech/contracts/L1/gateways/IL1GatewayRouter.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.16;\n\nimport {IL1ETHGateway} from \"./IL1ETHGateway.sol\";\nimport {IL1ERC20Gateway} from \"./IL1ERC20Gateway.sol\";\n\ninterface IL1GatewayRouter is IL1ETHGateway, IL1ERC20Gateway {\n /**********\n * Events *\n **********/\n\n /// @notice Emitted when the address of ETH Gateway is updated.\n /// @param ethGateway The address of new ETH Gateway.\n event SetETHGateway(address indexed ethGateway);\n\n /// @notice Emitted when the address of default ERC20 Gateway is updated.\n /// @param defaultERC20Gateway The address of new default ERC20 Gateway.\n event SetDefaultERC20Gateway(address indexed defaultERC20Gateway);\n\n /// @notice Emitted when the `gateway` for `token` is updated.\n /// @param token The address of token updated.\n /// @param gateway The corresponding address of gateway updated.\n event SetERC20Gateway(address indexed token, address indexed gateway);\n\n /*************************\n * Public View Functions *\n *************************/\n\n /// @notice Return the corresponding gateway address for given token address.\n /// @param _token The address of token to query.\n function getERC20Gateway(address _token) external view returns (address);\n\n /*****************************\n * Public Mutating Functions *\n *****************************/\n\n /// @notice Request ERC20 token transfer from users to gateways.\n /// @param sender The address of sender to request fund.\n /// @param token The address of token to request.\n /// @param amount The amount of token to request.\n function requestERC20(\n address sender,\n address token,\n uint256 amount\n ) external returns (uint256);\n\n /************************\n * Restricted Functions *\n ************************/\n\n /// @notice Update the address of ETH gateway contract.\n /// @dev This function should only be called by contract owner.\n /// @param _ethGateway The address to update.\n function setETHGateway(address _ethGateway) external;\n\n /// @notice Update the address of default ERC20 gateway contract.\n /// @dev This function should only be called by contract owner.\n /// @param _defaultERC20Gateway The address to update.\n function setDefaultERC20Gateway(address _defaultERC20Gateway) external;\n\n /// @notice Update the mapping from token address to gateway address.\n /// @dev This function should only be called by contract owner.\n /// @param _tokens The list of addresses of tokens to update.\n /// @param _gateways The list of addresses of gateways to update.\n function setERC20Gateway(address[] memory _tokens, address[] memory _gateways) external;\n}\n" + }, + "@scroll-tech/contracts/L1/IL1ScrollMessenger.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.16;\n\nimport {IScrollMessenger} from \"../libraries/IScrollMessenger.sol\";\n\ninterface IL1ScrollMessenger is IScrollMessenger {\n /**********\n * Events *\n **********/\n\n /// @notice Emitted when the maximum number of times each message can be replayed is updated.\n /// @param maxReplayTimes The new maximum number of times each message can be replayed.\n event UpdateMaxReplayTimes(uint256 maxReplayTimes);\n\n /***********\n * Structs *\n ***********/\n\n struct L2MessageProof {\n // The index of the batch where the message belongs to.\n uint256 batchIndex;\n // Concatenation of merkle proof for withdraw merkle trie.\n bytes merkleProof;\n }\n\n /*****************************\n * Public Mutating Functions *\n *****************************/\n\n /// @notice Relay a L2 => L1 message with message proof.\n /// @param from The address of the sender of the message.\n /// @param to The address of the recipient of the message.\n /// @param value The msg.value passed to the message call.\n /// @param nonce The nonce of the message to avoid replay attack.\n /// @param message The content of the message.\n /// @param proof The proof used to verify the correctness of the transaction.\n function relayMessageWithProof(\n address from,\n address to,\n uint256 value,\n uint256 nonce,\n bytes memory message,\n L2MessageProof memory proof\n ) external;\n\n /// @notice Replay an existing message.\n /// @param from The address of the sender of the message.\n /// @param to The address of the recipient of the message.\n /// @param value The msg.value passed to the message call.\n /// @param messageNonce The nonce for the message to replay.\n /// @param message The content of the message.\n /// @param newGasLimit New gas limit to be used for this message.\n /// @param refundAddress The address of account who will receive the refunded fee.\n function replayMessage(\n address from,\n address to,\n uint256 value,\n uint256 messageNonce,\n bytes memory message,\n uint32 newGasLimit,\n address refundAddress\n ) external payable;\n\n /// @notice Drop a skipped message.\n /// @param from The address of the sender of the message.\n /// @param to The address of the recipient of the message.\n /// @param value The msg.value passed to the message call.\n /// @param messageNonce The nonce for the message to drop.\n /// @param message The content of the message.\n function dropMessage(\n address from,\n address to,\n uint256 value,\n uint256 messageNonce,\n bytes memory message\n ) external;\n}\n" + }, + "@scroll-tech/contracts/L1/rollup/IL2GasPriceOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.16;\n\ninterface IL2GasPriceOracle {\n /// @notice Estimate fee for cross chain message call.\n /// @param _gasLimit Gas limit required to complete the message relay on L2.\n function estimateCrossDomainMessageFee(uint256 _gasLimit) external view returns (uint256);\n\n /// @notice Estimate intrinsic gas fee for cross chain message call.\n /// @param _message The message to be relayed on L2.\n function calculateIntrinsicGasFee(bytes memory _message) external view returns (uint256);\n}\n" + }, + "@scroll-tech/contracts/L2/gateways/IL2ERC20Gateway.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.16;\n\ninterface IL2ERC20Gateway {\n /**********\n * Events *\n **********/\n\n /// @notice Emitted when ERC20 token is deposited from L1 to L2 and transfer to recipient.\n /// @param l1Token The address of the token in L1.\n /// @param l2Token The address of the token in L2.\n /// @param from The address of sender in L1.\n /// @param to The address of recipient in L2.\n /// @param amount The amount of token withdrawn from L1 to L2.\n /// @param data The optional calldata passed to recipient in L2.\n event FinalizeDepositERC20(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n /// @notice Emitted when someone withdraw ERC20 token from L2 to L1.\n /// @param l1Token The address of the token in L1.\n /// @param l2Token The address of the token in L2.\n /// @param from The address of sender in L2.\n /// @param to The address of recipient in L1.\n /// @param amount The amount of token will be deposited from L2 to L1.\n /// @param data The optional calldata passed to recipient in L1.\n event WithdrawERC20(\n address indexed l1Token,\n address indexed l2Token,\n address indexed from,\n address to,\n uint256 amount,\n bytes data\n );\n\n /*************************\n * Public View Functions *\n *************************/\n\n /// @notice Return the corresponding l1 token address given l2 token address.\n /// @param l2Token The address of l2 token.\n function getL1ERC20Address(address l2Token) external view returns (address);\n\n /// @notice Return the corresponding l2 token address given l1 token address.\n /// @param l1Token The address of l1 token.\n function getL2ERC20Address(address l1Token) external view returns (address);\n\n /*****************************\n * Public Mutating Functions *\n *****************************/\n\n /// @notice Withdraw of some token to a caller's account on L1.\n /// @dev Make this function payable to send relayer fee in Ether.\n /// @param token The address of token in L2.\n /// @param amount The amount of token to transfer.\n /// @param gasLimit Unused, but included for potential forward compatibility considerations.\n function withdrawERC20(\n address token,\n uint256 amount,\n uint256 gasLimit\n ) external payable;\n\n /// @notice Withdraw of some token to a recipient's account on L1.\n /// @dev Make this function payable to send relayer fee in Ether.\n /// @param token The address of token in L2.\n /// @param to The address of recipient's account on L1.\n /// @param amount The amount of token to transfer.\n /// @param gasLimit Unused, but included for potential forward compatibility considerations.\n function withdrawERC20(\n address token,\n address to,\n uint256 amount,\n uint256 gasLimit\n ) external payable;\n\n /// @notice Withdraw of some token to a recipient's account on L1 and call.\n /// @dev Make this function payable to send relayer fee in Ether.\n /// @param token The address of token in L2.\n /// @param to The address of recipient's account on L1.\n /// @param amount The amount of token to transfer.\n /// @param data Optional data to forward to recipient's account.\n /// @param gasLimit Unused, but included for potential forward compatibility considerations.\n function withdrawERC20AndCall(\n address token,\n address to,\n uint256 amount,\n bytes calldata data,\n uint256 gasLimit\n ) external payable;\n\n /// @notice Complete a deposit from L1 to L2 and send fund to recipient's account in L2.\n /// @dev Make this function payable to handle WETH deposit/withdraw.\n /// The function should only be called by L2ScrollMessenger.\n /// The function should also only be called by L1ERC20Gateway in L1.\n /// @param l1Token The address of corresponding L1 token.\n /// @param l2Token The address of corresponding L2 token.\n /// @param from The address of account who deposits the token in L1.\n /// @param to The address of recipient in L2 to receive the token.\n /// @param amount The amount of the token to deposit.\n /// @param data Optional data to forward to recipient's account.\n function finalizeDepositERC20(\n address l1Token,\n address l2Token,\n address from,\n address to,\n uint256 amount,\n bytes calldata data\n ) external payable;\n}\n" + }, + "@scroll-tech/contracts/L2/gateways/IL2ETHGateway.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.16;\n\ninterface IL2ETHGateway {\n /**********\n * Events *\n **********/\n\n /// @notice Emitted when someone withdraw ETH from L2 to L1.\n /// @param from The address of sender in L2.\n /// @param to The address of recipient in L1.\n /// @param amount The amount of ETH will be deposited from L2 to L1.\n /// @param data The optional calldata passed to recipient in L1.\n event WithdrawETH(address indexed from, address indexed to, uint256 amount, bytes data);\n\n /// @notice Emitted when ETH is deposited from L1 to L2 and transfer to recipient.\n /// @param from The address of sender in L1.\n /// @param to The address of recipient in L2.\n /// @param amount The amount of ETH deposited from L1 to L2.\n /// @param data The optional calldata passed to recipient in L2.\n event FinalizeDepositETH(address indexed from, address indexed to, uint256 amount, bytes data);\n\n /*****************************\n * Public Mutating Functions *\n *****************************/\n\n /// @notice Withdraw ETH to caller's account in L1.\n /// @param amount The amount of ETH to be withdrawn.\n /// @param gasLimit Optional, gas limit used to complete the withdraw on L1.\n function withdrawETH(uint256 amount, uint256 gasLimit) external payable;\n\n /// @notice Withdraw ETH to caller's account in L1.\n /// @param to The address of recipient's account on L1.\n /// @param amount The amount of ETH to be withdrawn.\n /// @param gasLimit Optional, gas limit used to complete the withdraw on L1.\n function withdrawETH(\n address to,\n uint256 amount,\n uint256 gasLimit\n ) external payable;\n\n /// @notice Withdraw ETH to caller's account in L1.\n /// @param to The address of recipient's account on L1.\n /// @param amount The amount of ETH to be withdrawn.\n /// @param data Optional data to forward to recipient's account.\n /// @param gasLimit Optional, gas limit used to complete the withdraw on L1.\n function withdrawETHAndCall(\n address to,\n uint256 amount,\n bytes calldata data,\n uint256 gasLimit\n ) external payable;\n\n /// @notice Complete ETH deposit from L1 to L2 and send fund to recipient's account in L2.\n /// @dev This function should only be called by L2ScrollMessenger.\n /// This function should also only be called by L1GatewayRouter in L1.\n /// @param _from The address of account who deposit ETH in L1.\n /// @param _to The address of recipient in L2 to receive ETH.\n /// @param _amount The amount of ETH to deposit.\n /// @param _data Optional data to forward to recipient's account.\n function finalizeDepositETH(\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable;\n}\n" + }, + "@scroll-tech/contracts/L2/gateways/IL2GatewayRouter.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.16;\n\nimport {IL2ETHGateway} from \"./IL2ETHGateway.sol\";\nimport {IL2ERC20Gateway} from \"./IL2ERC20Gateway.sol\";\n\ninterface IL2GatewayRouter is IL2ETHGateway, IL2ERC20Gateway {\n /**********\n * Events *\n **********/\n\n /// @notice Emitted when the address of ETH Gateway is updated.\n /// @param ethGateway The address of new ETH Gateway.\n event SetETHGateway(address indexed ethGateway);\n\n /// @notice Emitted when the address of default ERC20 Gateway is updated.\n /// @param defaultERC20Gateway The address of new default ERC20 Gateway.\n event SetDefaultERC20Gateway(address indexed defaultERC20Gateway);\n\n /// @notice Emitted when the `gateway` for `token` is updated.\n /// @param token The address of token updated.\n /// @param gateway The corresponding address of gateway updated.\n event SetERC20Gateway(address indexed token, address indexed gateway);\n}\n" + }, + "@scroll-tech/contracts/libraries/IScrollMessenger.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.16;\n\ninterface IScrollMessenger {\n /**********\n * Events *\n **********/\n\n /// @notice Emitted when a cross domain message is sent.\n /// @param sender The address of the sender who initiates the message.\n /// @param target The address of target contract to call.\n /// @param value The amount of value passed to the target contract.\n /// @param messageNonce The nonce of the message.\n /// @param gasLimit The optional gas limit passed to L1 or L2.\n /// @param message The calldata passed to the target contract.\n event SentMessage(\n address indexed sender,\n address indexed target,\n uint256 value,\n uint256 messageNonce,\n uint256 gasLimit,\n bytes message\n );\n\n /// @notice Emitted when a cross domain message is relayed successfully.\n /// @param messageHash The hash of the message.\n event RelayedMessage(bytes32 indexed messageHash);\n\n /// @notice Emitted when a cross domain message is failed to relay.\n /// @param messageHash The hash of the message.\n event FailedRelayedMessage(bytes32 indexed messageHash);\n\n /*************************\n * Public View Functions *\n *************************/\n\n /// @notice Return the sender of a cross domain message.\n function xDomainMessageSender() external view returns (address);\n\n /*****************************\n * Public Mutating Functions *\n *****************************/\n\n /// @notice Send cross chain message from L1 to L2 or L2 to L1.\n /// @param target The address of account who receive the message.\n /// @param value The amount of ether passed when call target contract.\n /// @param message The content of the message.\n /// @param gasLimit Gas limit required to complete the message relay on corresponding chain.\n function sendMessage(\n address target,\n uint256 value,\n bytes calldata message,\n uint256 gasLimit\n ) external payable;\n\n /// @notice Send cross chain message from L1 to L2 or L2 to L1.\n /// @param target The address of account who receive the message.\n /// @param value The amount of ether passed when call target contract.\n /// @param message The content of the message.\n /// @param gasLimit Gas limit required to complete the message relay on corresponding chain.\n /// @param refundAddress The address of account who will receive the refunded fee.\n function sendMessage(\n address target,\n uint256 value,\n bytes calldata message,\n uint256 gasLimit,\n address refundAddress\n ) external payable;\n}\n" + }, + "@uma/core/contracts/common/implementation/ExpandedERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"./MultiRole.sol\";\nimport \"../interfaces/ExpandedIERC20.sol\";\n\n/**\n * @title An ERC20 with permissioned burning and minting. The contract deployer will initially\n * be the owner who is capable of adding new roles.\n */\ncontract ExpandedERC20 is ExpandedIERC20, ERC20, MultiRole {\n enum Roles {\n // Can set the minter and burner.\n Owner,\n // Addresses that can mint new tokens.\n Minter,\n // Addresses that can burn tokens that address owns.\n Burner\n }\n\n uint8 _decimals;\n\n /**\n * @notice Constructs the ExpandedERC20.\n * @param _tokenName The name which describes the new token.\n * @param _tokenSymbol The ticker abbreviation of the name. Ideally < 5 chars.\n * @param _tokenDecimals The number of decimals to define token precision.\n */\n constructor(\n string memory _tokenName,\n string memory _tokenSymbol,\n uint8 _tokenDecimals\n ) ERC20(_tokenName, _tokenSymbol) {\n _decimals = _tokenDecimals;\n _createExclusiveRole(uint256(Roles.Owner), uint256(Roles.Owner), msg.sender);\n _createSharedRole(uint256(Roles.Minter), uint256(Roles.Owner), new address[](0));\n _createSharedRole(uint256(Roles.Burner), uint256(Roles.Owner), new address[](0));\n }\n\n function decimals() public view virtual override(ERC20) returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev Mints `value` tokens to `recipient`, returning true on success.\n * @param recipient address to mint to.\n * @param value amount of tokens to mint.\n * @return True if the mint succeeded, or False.\n */\n function mint(address recipient, uint256 value)\n external\n override\n onlyRoleHolder(uint256(Roles.Minter))\n returns (bool)\n {\n _mint(recipient, value);\n return true;\n }\n\n /**\n * @dev Burns `value` tokens owned by `msg.sender`.\n * @param value amount of tokens to burn.\n */\n function burn(uint256 value) external override onlyRoleHolder(uint256(Roles.Burner)) {\n _burn(msg.sender, value);\n }\n\n /**\n * @dev Burns `value` tokens owned by `recipient`.\n * @param recipient address to burn tokens from.\n * @param value amount of tokens to burn.\n * @return True if the burn succeeded, or False.\n */\n function burnFrom(address recipient, uint256 value)\n external\n override\n onlyRoleHolder(uint256(Roles.Burner))\n returns (bool)\n {\n _burn(recipient, value);\n return true;\n }\n\n /**\n * @notice Add Minter role to account.\n * @dev The caller must have the Owner role.\n * @param account The address to which the Minter role is added.\n */\n function addMinter(address account) external virtual override {\n addMember(uint256(Roles.Minter), account);\n }\n\n /**\n * @notice Add Burner role to account.\n * @dev The caller must have the Owner role.\n * @param account The address to which the Burner role is added.\n */\n function addBurner(address account) external virtual override {\n addMember(uint256(Roles.Burner), account);\n }\n\n /**\n * @notice Reset Owner role to account.\n * @dev The caller must have the Owner role.\n * @param account The new holder of the Owner role.\n */\n function resetOwner(address account) external virtual override {\n resetMember(uint256(Roles.Owner), account);\n }\n}\n" + }, + "@uma/core/contracts/common/implementation/FixedPoint.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/utils/math/SignedSafeMath.sol\";\n\n/**\n * @title Library for fixed point arithmetic on uints\n */\nlibrary FixedPoint {\n using SafeMath for uint256;\n using SignedSafeMath for int256;\n\n // Supports 18 decimals. E.g., 1e18 represents \"1\", 5e17 represents \"0.5\".\n // For unsigned values:\n // This can represent a value up to (2^256 - 1)/10^18 = ~10^59. 10^59 will be stored internally as uint256 10^77.\n uint256 private constant FP_SCALING_FACTOR = 10**18;\n\n // --------------------------------------- UNSIGNED -----------------------------------------------------------------------------\n struct Unsigned {\n uint256 rawValue;\n }\n\n /**\n * @notice Constructs an `Unsigned` from an unscaled uint, e.g., `b=5` gets stored internally as `5*(10**18)`.\n * @param a uint to convert into a FixedPoint.\n * @return the converted FixedPoint.\n */\n function fromUnscaledUint(uint256 a) internal pure returns (Unsigned memory) {\n return Unsigned(a.mul(FP_SCALING_FACTOR));\n }\n\n /**\n * @notice Whether `a` is equal to `b`.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return True if equal, or False.\n */\n function isEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {\n return a.rawValue == fromUnscaledUint(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is equal to `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return True if equal, or False.\n */\n function isEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {\n return a.rawValue == b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return True if `a > b`, or False.\n */\n function isGreaterThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {\n return a.rawValue > b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than `b`.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return True if `a > b`, or False.\n */\n function isGreaterThan(Unsigned memory a, uint256 b) internal pure returns (bool) {\n return a.rawValue > fromUnscaledUint(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than `b`.\n * @param a a uint256.\n * @param b a FixedPoint.\n * @return True if `a > b`, or False.\n */\n function isGreaterThan(uint256 a, Unsigned memory b) internal pure returns (bool) {\n return fromUnscaledUint(a).rawValue > b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than or equal to `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return True if `a >= b`, or False.\n */\n function isGreaterThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {\n return a.rawValue >= b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than or equal to `b`.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return True if `a >= b`, or False.\n */\n function isGreaterThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {\n return a.rawValue >= fromUnscaledUint(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than or equal to `b`.\n * @param a a uint256.\n * @param b a FixedPoint.\n * @return True if `a >= b`, or False.\n */\n function isGreaterThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) {\n return fromUnscaledUint(a).rawValue >= b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return True if `a < b`, or False.\n */\n function isLessThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {\n return a.rawValue < b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than `b`.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return True if `a < b`, or False.\n */\n function isLessThan(Unsigned memory a, uint256 b) internal pure returns (bool) {\n return a.rawValue < fromUnscaledUint(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is less than `b`.\n * @param a a uint256.\n * @param b a FixedPoint.\n * @return True if `a < b`, or False.\n */\n function isLessThan(uint256 a, Unsigned memory b) internal pure returns (bool) {\n return fromUnscaledUint(a).rawValue < b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than or equal to `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return True if `a <= b`, or False.\n */\n function isLessThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {\n return a.rawValue <= b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than or equal to `b`.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return True if `a <= b`, or False.\n */\n function isLessThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {\n return a.rawValue <= fromUnscaledUint(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is less than or equal to `b`.\n * @param a a uint256.\n * @param b a FixedPoint.\n * @return True if `a <= b`, or False.\n */\n function isLessThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) {\n return fromUnscaledUint(a).rawValue <= b.rawValue;\n }\n\n /**\n * @notice The minimum of `a` and `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the minimum of `a` and `b`.\n */\n function min(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n return a.rawValue < b.rawValue ? a : b;\n }\n\n /**\n * @notice The maximum of `a` and `b`.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the maximum of `a` and `b`.\n */\n function max(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n return a.rawValue > b.rawValue ? a : b;\n }\n\n /**\n * @notice Adds two `Unsigned`s, reverting on overflow.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the sum of `a` and `b`.\n */\n function add(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n return Unsigned(a.rawValue.add(b.rawValue));\n }\n\n /**\n * @notice Adds an `Unsigned` to an unscaled uint, reverting on overflow.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return the sum of `a` and `b`.\n */\n function add(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {\n return add(a, fromUnscaledUint(b));\n }\n\n /**\n * @notice Subtracts two `Unsigned`s, reverting on overflow.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the difference of `a` and `b`.\n */\n function sub(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n return Unsigned(a.rawValue.sub(b.rawValue));\n }\n\n /**\n * @notice Subtracts an unscaled uint256 from an `Unsigned`, reverting on overflow.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return the difference of `a` and `b`.\n */\n function sub(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {\n return sub(a, fromUnscaledUint(b));\n }\n\n /**\n * @notice Subtracts an `Unsigned` from an unscaled uint256, reverting on overflow.\n * @param a a uint256.\n * @param b a FixedPoint.\n * @return the difference of `a` and `b`.\n */\n function sub(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) {\n return sub(fromUnscaledUint(a), b);\n }\n\n /**\n * @notice Multiplies two `Unsigned`s, reverting on overflow.\n * @dev This will \"floor\" the product.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the product of `a` and `b`.\n */\n function mul(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n // There are two caveats with this computation:\n // 1. Max output for the represented number is ~10^41, otherwise an intermediate value overflows. 10^41 is\n // stored internally as a uint256 ~10^59.\n // 2. Results that can't be represented exactly are truncated not rounded. E.g., 1.4 * 2e-18 = 2.8e-18, which\n // would round to 3, but this computation produces the result 2.\n // No need to use SafeMath because FP_SCALING_FACTOR != 0.\n return Unsigned(a.rawValue.mul(b.rawValue) / FP_SCALING_FACTOR);\n }\n\n /**\n * @notice Multiplies an `Unsigned` and an unscaled uint256, reverting on overflow.\n * @dev This will \"floor\" the product.\n * @param a a FixedPoint.\n * @param b a uint256.\n * @return the product of `a` and `b`.\n */\n function mul(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {\n return Unsigned(a.rawValue.mul(b));\n }\n\n /**\n * @notice Multiplies two `Unsigned`s and \"ceil's\" the product, reverting on overflow.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the product of `a` and `b`.\n */\n function mulCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n uint256 mulRaw = a.rawValue.mul(b.rawValue);\n uint256 mulFloor = mulRaw / FP_SCALING_FACTOR;\n uint256 mod = mulRaw.mod(FP_SCALING_FACTOR);\n if (mod != 0) {\n return Unsigned(mulFloor.add(1));\n } else {\n return Unsigned(mulFloor);\n }\n }\n\n /**\n * @notice Multiplies an `Unsigned` and an unscaled uint256 and \"ceil's\" the product, reverting on overflow.\n * @param a a FixedPoint.\n * @param b a FixedPoint.\n * @return the product of `a` and `b`.\n */\n function mulCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {\n // Since b is an uint, there is no risk of truncation and we can just mul it normally\n return Unsigned(a.rawValue.mul(b));\n }\n\n /**\n * @notice Divides one `Unsigned` by an `Unsigned`, reverting on overflow or division by 0.\n * @dev This will \"floor\" the quotient.\n * @param a a FixedPoint numerator.\n * @param b a FixedPoint denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function div(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n // There are two caveats with this computation:\n // 1. Max value for the number dividend `a` represents is ~10^41, otherwise an intermediate value overflows.\n // 10^41 is stored internally as a uint256 10^59.\n // 2. Results that can't be represented exactly are truncated not rounded. E.g., 2 / 3 = 0.6 repeating, which\n // would round to 0.666666666666666667, but this computation produces the result 0.666666666666666666.\n return Unsigned(a.rawValue.mul(FP_SCALING_FACTOR).div(b.rawValue));\n }\n\n /**\n * @notice Divides one `Unsigned` by an unscaled uint256, reverting on overflow or division by 0.\n * @dev This will \"floor\" the quotient.\n * @param a a FixedPoint numerator.\n * @param b a uint256 denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function div(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {\n return Unsigned(a.rawValue.div(b));\n }\n\n /**\n * @notice Divides one unscaled uint256 by an `Unsigned`, reverting on overflow or division by 0.\n * @dev This will \"floor\" the quotient.\n * @param a a uint256 numerator.\n * @param b a FixedPoint denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function div(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) {\n return div(fromUnscaledUint(a), b);\n }\n\n /**\n * @notice Divides one `Unsigned` by an `Unsigned` and \"ceil's\" the quotient, reverting on overflow or division by 0.\n * @param a a FixedPoint numerator.\n * @param b a FixedPoint denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function divCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {\n uint256 aScaled = a.rawValue.mul(FP_SCALING_FACTOR);\n uint256 divFloor = aScaled.div(b.rawValue);\n uint256 mod = aScaled.mod(b.rawValue);\n if (mod != 0) {\n return Unsigned(divFloor.add(1));\n } else {\n return Unsigned(divFloor);\n }\n }\n\n /**\n * @notice Divides one `Unsigned` by an unscaled uint256 and \"ceil's\" the quotient, reverting on overflow or division by 0.\n * @param a a FixedPoint numerator.\n * @param b a uint256 denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function divCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {\n // Because it is possible that a quotient gets truncated, we can't just call \"Unsigned(a.rawValue.div(b))\"\n // similarly to mulCeil with a uint256 as the second parameter. Therefore we need to convert b into an Unsigned.\n // This creates the possibility of overflow if b is very large.\n return divCeil(a, fromUnscaledUint(b));\n }\n\n /**\n * @notice Raises an `Unsigned` to the power of an unscaled uint256, reverting on overflow. E.g., `b=2` squares `a`.\n * @dev This will \"floor\" the result.\n * @param a a FixedPoint numerator.\n * @param b a uint256 denominator.\n * @return output is `a` to the power of `b`.\n */\n function pow(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory output) {\n output = fromUnscaledUint(1);\n for (uint256 i = 0; i < b; i = i.add(1)) {\n output = mul(output, a);\n }\n }\n\n // ------------------------------------------------- SIGNED -------------------------------------------------------------\n // Supports 18 decimals. E.g., 1e18 represents \"1\", 5e17 represents \"0.5\".\n // For signed values:\n // This can represent a value up (or down) to +-(2^255 - 1)/10^18 = ~10^58. 10^58 will be stored internally as int256 10^76.\n int256 private constant SFP_SCALING_FACTOR = 10**18;\n\n struct Signed {\n int256 rawValue;\n }\n\n function fromSigned(Signed memory a) internal pure returns (Unsigned memory) {\n require(a.rawValue >= 0, \"Negative value provided\");\n return Unsigned(uint256(a.rawValue));\n }\n\n function fromUnsigned(Unsigned memory a) internal pure returns (Signed memory) {\n require(a.rawValue <= uint256(type(int256).max), \"Unsigned too large\");\n return Signed(int256(a.rawValue));\n }\n\n /**\n * @notice Constructs a `Signed` from an unscaled int, e.g., `b=5` gets stored internally as `5*(10**18)`.\n * @param a int to convert into a FixedPoint.Signed.\n * @return the converted FixedPoint.Signed.\n */\n function fromUnscaledInt(int256 a) internal pure returns (Signed memory) {\n return Signed(a.mul(SFP_SCALING_FACTOR));\n }\n\n /**\n * @notice Whether `a` is equal to `b`.\n * @param a a FixedPoint.Signed.\n * @param b a int256.\n * @return True if equal, or False.\n */\n function isEqual(Signed memory a, int256 b) internal pure returns (bool) {\n return a.rawValue == fromUnscaledInt(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is equal to `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return True if equal, or False.\n */\n function isEqual(Signed memory a, Signed memory b) internal pure returns (bool) {\n return a.rawValue == b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return True if `a > b`, or False.\n */\n function isGreaterThan(Signed memory a, Signed memory b) internal pure returns (bool) {\n return a.rawValue > b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than `b`.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return True if `a > b`, or False.\n */\n function isGreaterThan(Signed memory a, int256 b) internal pure returns (bool) {\n return a.rawValue > fromUnscaledInt(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than `b`.\n * @param a an int256.\n * @param b a FixedPoint.Signed.\n * @return True if `a > b`, or False.\n */\n function isGreaterThan(int256 a, Signed memory b) internal pure returns (bool) {\n return fromUnscaledInt(a).rawValue > b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than or equal to `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return True if `a >= b`, or False.\n */\n function isGreaterThanOrEqual(Signed memory a, Signed memory b) internal pure returns (bool) {\n return a.rawValue >= b.rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than or equal to `b`.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return True if `a >= b`, or False.\n */\n function isGreaterThanOrEqual(Signed memory a, int256 b) internal pure returns (bool) {\n return a.rawValue >= fromUnscaledInt(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is greater than or equal to `b`.\n * @param a an int256.\n * @param b a FixedPoint.Signed.\n * @return True if `a >= b`, or False.\n */\n function isGreaterThanOrEqual(int256 a, Signed memory b) internal pure returns (bool) {\n return fromUnscaledInt(a).rawValue >= b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return True if `a < b`, or False.\n */\n function isLessThan(Signed memory a, Signed memory b) internal pure returns (bool) {\n return a.rawValue < b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than `b`.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return True if `a < b`, or False.\n */\n function isLessThan(Signed memory a, int256 b) internal pure returns (bool) {\n return a.rawValue < fromUnscaledInt(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is less than `b`.\n * @param a an int256.\n * @param b a FixedPoint.Signed.\n * @return True if `a < b`, or False.\n */\n function isLessThan(int256 a, Signed memory b) internal pure returns (bool) {\n return fromUnscaledInt(a).rawValue < b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than or equal to `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return True if `a <= b`, or False.\n */\n function isLessThanOrEqual(Signed memory a, Signed memory b) internal pure returns (bool) {\n return a.rawValue <= b.rawValue;\n }\n\n /**\n * @notice Whether `a` is less than or equal to `b`.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return True if `a <= b`, or False.\n */\n function isLessThanOrEqual(Signed memory a, int256 b) internal pure returns (bool) {\n return a.rawValue <= fromUnscaledInt(b).rawValue;\n }\n\n /**\n * @notice Whether `a` is less than or equal to `b`.\n * @param a an int256.\n * @param b a FixedPoint.Signed.\n * @return True if `a <= b`, or False.\n */\n function isLessThanOrEqual(int256 a, Signed memory b) internal pure returns (bool) {\n return fromUnscaledInt(a).rawValue <= b.rawValue;\n }\n\n /**\n * @notice The minimum of `a` and `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the minimum of `a` and `b`.\n */\n function min(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n return a.rawValue < b.rawValue ? a : b;\n }\n\n /**\n * @notice The maximum of `a` and `b`.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the maximum of `a` and `b`.\n */\n function max(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n return a.rawValue > b.rawValue ? a : b;\n }\n\n /**\n * @notice Adds two `Signed`s, reverting on overflow.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the sum of `a` and `b`.\n */\n function add(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n return Signed(a.rawValue.add(b.rawValue));\n }\n\n /**\n * @notice Adds an `Signed` to an unscaled int, reverting on overflow.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return the sum of `a` and `b`.\n */\n function add(Signed memory a, int256 b) internal pure returns (Signed memory) {\n return add(a, fromUnscaledInt(b));\n }\n\n /**\n * @notice Subtracts two `Signed`s, reverting on overflow.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the difference of `a` and `b`.\n */\n function sub(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n return Signed(a.rawValue.sub(b.rawValue));\n }\n\n /**\n * @notice Subtracts an unscaled int256 from an `Signed`, reverting on overflow.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return the difference of `a` and `b`.\n */\n function sub(Signed memory a, int256 b) internal pure returns (Signed memory) {\n return sub(a, fromUnscaledInt(b));\n }\n\n /**\n * @notice Subtracts an `Signed` from an unscaled int256, reverting on overflow.\n * @param a an int256.\n * @param b a FixedPoint.Signed.\n * @return the difference of `a` and `b`.\n */\n function sub(int256 a, Signed memory b) internal pure returns (Signed memory) {\n return sub(fromUnscaledInt(a), b);\n }\n\n /**\n * @notice Multiplies two `Signed`s, reverting on overflow.\n * @dev This will \"floor\" the product.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the product of `a` and `b`.\n */\n function mul(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n // There are two caveats with this computation:\n // 1. Max output for the represented number is ~10^41, otherwise an intermediate value overflows. 10^41 is\n // stored internally as an int256 ~10^59.\n // 2. Results that can't be represented exactly are truncated not rounded. E.g., 1.4 * 2e-18 = 2.8e-18, which\n // would round to 3, but this computation produces the result 2.\n // No need to use SafeMath because SFP_SCALING_FACTOR != 0.\n return Signed(a.rawValue.mul(b.rawValue) / SFP_SCALING_FACTOR);\n }\n\n /**\n * @notice Multiplies an `Signed` and an unscaled int256, reverting on overflow.\n * @dev This will \"floor\" the product.\n * @param a a FixedPoint.Signed.\n * @param b an int256.\n * @return the product of `a` and `b`.\n */\n function mul(Signed memory a, int256 b) internal pure returns (Signed memory) {\n return Signed(a.rawValue.mul(b));\n }\n\n /**\n * @notice Multiplies two `Signed`s and \"ceil's\" the product, reverting on overflow.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the product of `a` and `b`.\n */\n function mulAwayFromZero(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n int256 mulRaw = a.rawValue.mul(b.rawValue);\n int256 mulTowardsZero = mulRaw / SFP_SCALING_FACTOR;\n // Manual mod because SignedSafeMath doesn't support it.\n int256 mod = mulRaw % SFP_SCALING_FACTOR;\n if (mod != 0) {\n bool isResultPositive = isLessThan(a, 0) == isLessThan(b, 0);\n int256 valueToAdd = isResultPositive ? int256(1) : int256(-1);\n return Signed(mulTowardsZero.add(valueToAdd));\n } else {\n return Signed(mulTowardsZero);\n }\n }\n\n /**\n * @notice Multiplies an `Signed` and an unscaled int256 and \"ceil's\" the product, reverting on overflow.\n * @param a a FixedPoint.Signed.\n * @param b a FixedPoint.Signed.\n * @return the product of `a` and `b`.\n */\n function mulAwayFromZero(Signed memory a, int256 b) internal pure returns (Signed memory) {\n // Since b is an int, there is no risk of truncation and we can just mul it normally\n return Signed(a.rawValue.mul(b));\n }\n\n /**\n * @notice Divides one `Signed` by an `Signed`, reverting on overflow or division by 0.\n * @dev This will \"floor\" the quotient.\n * @param a a FixedPoint numerator.\n * @param b a FixedPoint denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function div(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n // There are two caveats with this computation:\n // 1. Max value for the number dividend `a` represents is ~10^41, otherwise an intermediate value overflows.\n // 10^41 is stored internally as an int256 10^59.\n // 2. Results that can't be represented exactly are truncated not rounded. E.g., 2 / 3 = 0.6 repeating, which\n // would round to 0.666666666666666667, but this computation produces the result 0.666666666666666666.\n return Signed(a.rawValue.mul(SFP_SCALING_FACTOR).div(b.rawValue));\n }\n\n /**\n * @notice Divides one `Signed` by an unscaled int256, reverting on overflow or division by 0.\n * @dev This will \"floor\" the quotient.\n * @param a a FixedPoint numerator.\n * @param b an int256 denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function div(Signed memory a, int256 b) internal pure returns (Signed memory) {\n return Signed(a.rawValue.div(b));\n }\n\n /**\n * @notice Divides one unscaled int256 by an `Signed`, reverting on overflow or division by 0.\n * @dev This will \"floor\" the quotient.\n * @param a an int256 numerator.\n * @param b a FixedPoint denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function div(int256 a, Signed memory b) internal pure returns (Signed memory) {\n return div(fromUnscaledInt(a), b);\n }\n\n /**\n * @notice Divides one `Signed` by an `Signed` and \"ceil's\" the quotient, reverting on overflow or division by 0.\n * @param a a FixedPoint numerator.\n * @param b a FixedPoint denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function divAwayFromZero(Signed memory a, Signed memory b) internal pure returns (Signed memory) {\n int256 aScaled = a.rawValue.mul(SFP_SCALING_FACTOR);\n int256 divTowardsZero = aScaled.div(b.rawValue);\n // Manual mod because SignedSafeMath doesn't support it.\n int256 mod = aScaled % b.rawValue;\n if (mod != 0) {\n bool isResultPositive = isLessThan(a, 0) == isLessThan(b, 0);\n int256 valueToAdd = isResultPositive ? int256(1) : int256(-1);\n return Signed(divTowardsZero.add(valueToAdd));\n } else {\n return Signed(divTowardsZero);\n }\n }\n\n /**\n * @notice Divides one `Signed` by an unscaled int256 and \"ceil's\" the quotient, reverting on overflow or division by 0.\n * @param a a FixedPoint numerator.\n * @param b an int256 denominator.\n * @return the quotient of `a` divided by `b`.\n */\n function divAwayFromZero(Signed memory a, int256 b) internal pure returns (Signed memory) {\n // Because it is possible that a quotient gets truncated, we can't just call \"Signed(a.rawValue.div(b))\"\n // similarly to mulCeil with an int256 as the second parameter. Therefore we need to convert b into an Signed.\n // This creates the possibility of overflow if b is very large.\n return divAwayFromZero(a, fromUnscaledInt(b));\n }\n\n /**\n * @notice Raises an `Signed` to the power of an unscaled uint256, reverting on overflow. E.g., `b=2` squares `a`.\n * @dev This will \"floor\" the result.\n * @param a a FixedPoint.Signed.\n * @param b a uint256 (negative exponents are not allowed).\n * @return output is `a` to the power of `b`.\n */\n function pow(Signed memory a, uint256 b) internal pure returns (Signed memory output) {\n output = fromUnscaledInt(1);\n for (uint256 i = 0; i < b; i = i.add(1)) {\n output = mul(output, a);\n }\n }\n}\n" + }, + "@uma/core/contracts/common/implementation/MultiCaller.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n// This contract is taken from Uniswap's multi call implementation (https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/base/Multicall.sol)\n// and was modified to be solidity 0.8 compatible. Additionally, the method was restricted to only work with msg.value\n// set to 0 to avoid any nasty attack vectors on function calls that use value sent with deposits.\n\n/// @title MultiCaller\n/// @notice Enables calling multiple methods in a single call to the contract\ncontract MultiCaller {\n function multicall(bytes[] calldata data) external returns (bytes[] memory results) {\n results = new bytes[](data.length);\n for (uint256 i = 0; i < data.length; i++) {\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\n\n if (!success) {\n // Next 5 lines from https://ethereum.stackexchange.com/a/83577\n if (result.length < 68) revert();\n assembly {\n result := add(result, 0x04)\n }\n revert(abi.decode(result, (string)));\n }\n\n results[i] = result;\n }\n }\n}\n" + }, + "@uma/core/contracts/common/implementation/MultiRole.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nlibrary Exclusive {\n struct RoleMembership {\n address member;\n }\n\n function isMember(RoleMembership storage roleMembership, address memberToCheck) internal view returns (bool) {\n return roleMembership.member == memberToCheck;\n }\n\n function resetMember(RoleMembership storage roleMembership, address newMember) internal {\n require(newMember != address(0x0), \"Cannot set an exclusive role to 0x0\");\n roleMembership.member = newMember;\n }\n\n function getMember(RoleMembership storage roleMembership) internal view returns (address) {\n return roleMembership.member;\n }\n\n function init(RoleMembership storage roleMembership, address initialMember) internal {\n resetMember(roleMembership, initialMember);\n }\n}\n\nlibrary Shared {\n struct RoleMembership {\n mapping(address => bool) members;\n }\n\n function isMember(RoleMembership storage roleMembership, address memberToCheck) internal view returns (bool) {\n return roleMembership.members[memberToCheck];\n }\n\n function addMember(RoleMembership storage roleMembership, address memberToAdd) internal {\n require(memberToAdd != address(0x0), \"Cannot add 0x0 to a shared role\");\n roleMembership.members[memberToAdd] = true;\n }\n\n function removeMember(RoleMembership storage roleMembership, address memberToRemove) internal {\n roleMembership.members[memberToRemove] = false;\n }\n\n function init(RoleMembership storage roleMembership, address[] memory initialMembers) internal {\n for (uint256 i = 0; i < initialMembers.length; i++) {\n addMember(roleMembership, initialMembers[i]);\n }\n }\n}\n\n/**\n * @title Base class to manage permissions for the derived class.\n */\nabstract contract MultiRole {\n using Exclusive for Exclusive.RoleMembership;\n using Shared for Shared.RoleMembership;\n\n enum RoleType { Invalid, Exclusive, Shared }\n\n struct Role {\n uint256 managingRole;\n RoleType roleType;\n Exclusive.RoleMembership exclusiveRoleMembership;\n Shared.RoleMembership sharedRoleMembership;\n }\n\n mapping(uint256 => Role) private roles;\n\n event ResetExclusiveMember(uint256 indexed roleId, address indexed newMember, address indexed manager);\n event AddedSharedMember(uint256 indexed roleId, address indexed newMember, address indexed manager);\n event RemovedSharedMember(uint256 indexed roleId, address indexed oldMember, address indexed manager);\n\n /**\n * @notice Reverts unless the caller is a member of the specified roleId.\n */\n modifier onlyRoleHolder(uint256 roleId) {\n require(holdsRole(roleId, msg.sender), \"Sender does not hold required role\");\n _;\n }\n\n /**\n * @notice Reverts unless the caller is a member of the manager role for the specified roleId.\n */\n modifier onlyRoleManager(uint256 roleId) {\n require(holdsRole(roles[roleId].managingRole, msg.sender), \"Can only be called by a role manager\");\n _;\n }\n\n /**\n * @notice Reverts unless the roleId represents an initialized, exclusive roleId.\n */\n modifier onlyExclusive(uint256 roleId) {\n require(roles[roleId].roleType == RoleType.Exclusive, \"Must be called on an initialized Exclusive role\");\n _;\n }\n\n /**\n * @notice Reverts unless the roleId represents an initialized, shared roleId.\n */\n modifier onlyShared(uint256 roleId) {\n require(roles[roleId].roleType == RoleType.Shared, \"Must be called on an initialized Shared role\");\n _;\n }\n\n /**\n * @notice Whether `memberToCheck` is a member of roleId.\n * @dev Reverts if roleId does not correspond to an initialized role.\n * @param roleId the Role to check.\n * @param memberToCheck the address to check.\n * @return True if `memberToCheck` is a member of `roleId`.\n */\n function holdsRole(uint256 roleId, address memberToCheck) public view returns (bool) {\n Role storage role = roles[roleId];\n if (role.roleType == RoleType.Exclusive) {\n return role.exclusiveRoleMembership.isMember(memberToCheck);\n } else if (role.roleType == RoleType.Shared) {\n return role.sharedRoleMembership.isMember(memberToCheck);\n }\n revert(\"Invalid roleId\");\n }\n\n /**\n * @notice Changes the exclusive role holder of `roleId` to `newMember`.\n * @dev Reverts if the caller is not a member of the managing role for `roleId` or if `roleId` is not an\n * initialized, ExclusiveRole.\n * @param roleId the ExclusiveRole membership to modify.\n * @param newMember the new ExclusiveRole member.\n */\n function resetMember(uint256 roleId, address newMember) public onlyExclusive(roleId) onlyRoleManager(roleId) {\n roles[roleId].exclusiveRoleMembership.resetMember(newMember);\n emit ResetExclusiveMember(roleId, newMember, msg.sender);\n }\n\n /**\n * @notice Gets the current holder of the exclusive role, `roleId`.\n * @dev Reverts if `roleId` does not represent an initialized, exclusive role.\n * @param roleId the ExclusiveRole membership to check.\n * @return the address of the current ExclusiveRole member.\n */\n function getMember(uint256 roleId) public view onlyExclusive(roleId) returns (address) {\n return roles[roleId].exclusiveRoleMembership.getMember();\n }\n\n /**\n * @notice Adds `newMember` to the shared role, `roleId`.\n * @dev Reverts if `roleId` does not represent an initialized, SharedRole or if the caller is not a member of the\n * managing role for `roleId`.\n * @param roleId the SharedRole membership to modify.\n * @param newMember the new SharedRole member.\n */\n function addMember(uint256 roleId, address newMember) public onlyShared(roleId) onlyRoleManager(roleId) {\n roles[roleId].sharedRoleMembership.addMember(newMember);\n emit AddedSharedMember(roleId, newMember, msg.sender);\n }\n\n /**\n * @notice Removes `memberToRemove` from the shared role, `roleId`.\n * @dev Reverts if `roleId` does not represent an initialized, SharedRole or if the caller is not a member of the\n * managing role for `roleId`.\n * @param roleId the SharedRole membership to modify.\n * @param memberToRemove the current SharedRole member to remove.\n */\n function removeMember(uint256 roleId, address memberToRemove) public onlyShared(roleId) onlyRoleManager(roleId) {\n roles[roleId].sharedRoleMembership.removeMember(memberToRemove);\n emit RemovedSharedMember(roleId, memberToRemove, msg.sender);\n }\n\n /**\n * @notice Removes caller from the role, `roleId`.\n * @dev Reverts if the caller is not a member of the role for `roleId` or if `roleId` is not an\n * initialized, SharedRole.\n * @param roleId the SharedRole membership to modify.\n */\n function renounceMembership(uint256 roleId) public onlyShared(roleId) onlyRoleHolder(roleId) {\n roles[roleId].sharedRoleMembership.removeMember(msg.sender);\n emit RemovedSharedMember(roleId, msg.sender, msg.sender);\n }\n\n /**\n * @notice Reverts if `roleId` is not initialized.\n */\n modifier onlyValidRole(uint256 roleId) {\n require(roles[roleId].roleType != RoleType.Invalid, \"Attempted to use an invalid roleId\");\n _;\n }\n\n /**\n * @notice Reverts if `roleId` is initialized.\n */\n modifier onlyInvalidRole(uint256 roleId) {\n require(roles[roleId].roleType == RoleType.Invalid, \"Cannot use a pre-existing role\");\n _;\n }\n\n /**\n * @notice Internal method to initialize a shared role, `roleId`, which will be managed by `managingRoleId`.\n * `initialMembers` will be immediately added to the role.\n * @dev Should be called by derived contracts, usually at construction time. Will revert if the role is already\n * initialized.\n */\n function _createSharedRole(\n uint256 roleId,\n uint256 managingRoleId,\n address[] memory initialMembers\n ) internal onlyInvalidRole(roleId) {\n Role storage role = roles[roleId];\n role.roleType = RoleType.Shared;\n role.managingRole = managingRoleId;\n role.sharedRoleMembership.init(initialMembers);\n require(\n roles[managingRoleId].roleType != RoleType.Invalid,\n \"Attempted to use an invalid role to manage a shared role\"\n );\n }\n\n /**\n * @notice Internal method to initialize an exclusive role, `roleId`, which will be managed by `managingRoleId`.\n * `initialMember` will be immediately added to the role.\n * @dev Should be called by derived contracts, usually at construction time. Will revert if the role is already\n * initialized.\n */\n function _createExclusiveRole(\n uint256 roleId,\n uint256 managingRoleId,\n address initialMember\n ) internal onlyInvalidRole(roleId) {\n Role storage role = roles[roleId];\n role.roleType = RoleType.Exclusive;\n role.managingRole = managingRoleId;\n role.exclusiveRoleMembership.init(initialMember);\n require(\n roles[managingRoleId].roleType != RoleType.Invalid,\n \"Attempted to use an invalid role to manage an exclusive role\"\n );\n }\n}\n" + }, + "@uma/core/contracts/common/implementation/Testable.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"./Timer.sol\";\n\n/**\n * @title Base class that provides time overrides, but only if being run in test mode.\n */\nabstract contract Testable {\n // If the contract is being run in production, then `timerAddress` will be the 0x0 address.\n // Note: this variable should be set on construction and never modified.\n address public timerAddress;\n\n /**\n * @notice Constructs the Testable contract. Called by child contracts.\n * @param _timerAddress Contract that stores the current time in a testing environment.\n * Must be set to 0x0 for production environments that use live time.\n */\n constructor(address _timerAddress) {\n timerAddress = _timerAddress;\n }\n\n /**\n * @notice Reverts if not running in test mode.\n */\n modifier onlyIfTest {\n require(timerAddress != address(0x0));\n _;\n }\n\n /**\n * @notice Sets the current time.\n * @dev Will revert if not running in test mode.\n * @param time timestamp to set current Testable time to.\n */\n function setCurrentTime(uint256 time) external onlyIfTest {\n Timer(timerAddress).setCurrentTime(time);\n }\n\n /**\n * @notice Gets the current time. Will return the last time set in `setCurrentTime` if running in test mode.\n * Otherwise, it will return the block timestamp.\n * @return uint for the current Testable timestamp.\n */\n function getCurrentTime() public view virtual returns (uint256) {\n if (timerAddress != address(0x0)) {\n return Timer(timerAddress).getCurrentTime();\n } else {\n return block.timestamp; // solhint-disable-line not-rely-on-time\n }\n }\n}\n" + }, + "@uma/core/contracts/common/implementation/Timer.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @title Universal store of current contract time for testing environments.\n */\ncontract Timer {\n uint256 private currentTime;\n\n constructor() {\n currentTime = block.timestamp; // solhint-disable-line not-rely-on-time\n }\n\n /**\n * @notice Sets the current time.\n * @dev Will revert if not running in test mode.\n * @param time timestamp to set `currentTime` to.\n */\n function setCurrentTime(uint256 time) external {\n currentTime = time;\n }\n\n /**\n * @notice Gets the currentTime variable set in the Timer.\n * @return uint256 for the current Testable timestamp.\n */\n function getCurrentTime() public view returns (uint256) {\n return currentTime;\n }\n}\n" + }, + "@uma/core/contracts/common/interfaces/AddressWhitelistInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\ninterface AddressWhitelistInterface {\n function addToWhitelist(address newElement) external;\n\n function removeFromWhitelist(address newElement) external;\n\n function isOnWhitelist(address newElement) external view returns (bool);\n\n function getWhitelist() external view returns (address[] memory);\n}\n" + }, + "@uma/core/contracts/common/interfaces/ExpandedIERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @title ERC20 interface that includes burn and mint methods.\n */\nabstract contract ExpandedIERC20 is IERC20 {\n /**\n * @notice Burns a specific amount of the caller's tokens.\n * @dev Only burns the caller's tokens, so it is safe to leave this method permissionless.\n */\n function burn(uint256 value) external virtual;\n\n /**\n * @dev Burns `value` tokens owned by `recipient`.\n * @param recipient address to burn tokens from.\n * @param value amount of tokens to burn.\n */\n function burnFrom(address recipient, uint256 value) external virtual returns (bool);\n\n /**\n * @notice Mints tokens and adds them to the balance of the `to` address.\n * @dev This method should be permissioned to only allow designated parties to mint tokens.\n */\n function mint(address to, uint256 value) external virtual returns (bool);\n\n function addMinter(address account) external virtual;\n\n function addBurner(address account) external virtual;\n\n function resetOwner(address account) external virtual;\n}\n" + }, + "@uma/core/contracts/data-verification-mechanism/implementation/Constants.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @title Stores common interface names used throughout the DVM by registration in the Finder.\n */\nlibrary OracleInterfaces {\n bytes32 public constant Oracle = \"Oracle\";\n bytes32 public constant IdentifierWhitelist = \"IdentifierWhitelist\";\n bytes32 public constant Store = \"Store\";\n bytes32 public constant FinancialContractsAdmin = \"FinancialContractsAdmin\";\n bytes32 public constant Registry = \"Registry\";\n bytes32 public constant CollateralWhitelist = \"CollateralWhitelist\";\n bytes32 public constant OptimisticOracle = \"OptimisticOracle\";\n bytes32 public constant OptimisticOracleV2 = \"OptimisticOracleV2\";\n bytes32 public constant OptimisticOracleV3 = \"OptimisticOracleV3\";\n bytes32 public constant Bridge = \"Bridge\";\n bytes32 public constant GenericHandler = \"GenericHandler\";\n bytes32 public constant SkinnyOptimisticOracle = \"SkinnyOptimisticOracle\";\n bytes32 public constant ChildMessenger = \"ChildMessenger\";\n bytes32 public constant OracleHub = \"OracleHub\";\n bytes32 public constant OracleSpoke = \"OracleSpoke\";\n}\n\n/**\n * @title Commonly re-used values for contracts associated with the OptimisticOracle.\n */\nlibrary OptimisticOracleConstraints {\n // Any price request submitted to the OptimisticOracle must contain ancillary data no larger than this value.\n // This value must be <= the Voting contract's `ancillaryBytesLimit` constant value otherwise it is possible\n // that a price can be requested to the OptimisticOracle successfully, but cannot be resolved by the DVM which\n // refuses to accept a price request made with ancillary data length over a certain size.\n uint256 public constant ancillaryBytesLimit = 8192;\n}\n" + }, + "@uma/core/contracts/data-verification-mechanism/interfaces/FinderInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @title Provides addresses of the live contracts implementing certain interfaces.\n * @dev Examples are the Oracle or Store interfaces.\n */\ninterface FinderInterface {\n /**\n * @notice Updates the address of the contract that implements `interfaceName`.\n * @param interfaceName bytes32 encoding of the interface name that is either changed or registered.\n * @param implementationAddress address of the deployed contract that implements the interface.\n */\n function changeImplementationAddress(bytes32 interfaceName, address implementationAddress) external;\n\n /**\n * @notice Gets the address of the contract that implements the given `interfaceName`.\n * @param interfaceName queried interface.\n * @return implementationAddress address of the deployed contract that implements the interface.\n */\n function getImplementationAddress(bytes32 interfaceName) external view returns (address);\n}\n" + }, + "@uma/core/contracts/data-verification-mechanism/interfaces/IdentifierWhitelistInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/**\n * @title Interface for whitelists of supported identifiers that the oracle can provide prices for.\n */\ninterface IdentifierWhitelistInterface {\n /**\n * @notice Adds the provided identifier as a supported identifier.\n * @dev Price requests using this identifier will succeed after this call.\n * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.\n */\n function addSupportedIdentifier(bytes32 identifier) external;\n\n /**\n * @notice Removes the identifier from the whitelist.\n * @dev Price requests using this identifier will no longer succeed after this call.\n * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.\n */\n function removeSupportedIdentifier(bytes32 identifier) external;\n\n /**\n * @notice Checks whether an identifier is on the whitelist.\n * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.\n * @return bool if the identifier is supported (or not).\n */\n function isIdentifierSupported(bytes32 identifier) external view returns (bool);\n}\n" + }, + "@uma/core/contracts/data-verification-mechanism/interfaces/StoreInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"../../common/implementation/FixedPoint.sol\";\n\n/**\n * @title Interface that allows financial contracts to pay oracle fees for their use of the system.\n */\ninterface StoreInterface {\n /**\n * @notice Pays Oracle fees in ETH to the store.\n * @dev To be used by contracts whose margin currency is ETH.\n */\n function payOracleFees() external payable;\n\n /**\n * @notice Pays oracle fees in the margin currency, erc20Address, to the store.\n * @dev To be used if the margin currency is an ERC20 token rather than ETH.\n * @param erc20Address address of the ERC20 token used to pay the fee.\n * @param amount number of tokens to transfer. An approval for at least this amount must exist.\n */\n function payOracleFeesErc20(address erc20Address, FixedPoint.Unsigned calldata amount) external;\n\n /**\n * @notice Computes the regular oracle fees that a contract should pay for a period.\n * @param startTime defines the beginning time from which the fee is paid.\n * @param endTime end time until which the fee is paid.\n * @param pfc \"profit from corruption\", or the maximum amount of margin currency that a\n * token sponsor could extract from the contract through corrupting the price feed in their favor.\n * @return regularFee amount owed for the duration from start to end time for the given pfc.\n * @return latePenalty for paying the fee after the deadline.\n */\n function computeRegularFee(\n uint256 startTime,\n uint256 endTime,\n FixedPoint.Unsigned calldata pfc\n ) external view returns (FixedPoint.Unsigned memory regularFee, FixedPoint.Unsigned memory latePenalty);\n\n /**\n * @notice Computes the final oracle fees that a contract should pay at settlement.\n * @param currency token used to pay the final fee.\n * @return finalFee amount due.\n */\n function computeFinalFee(address currency) external view returns (FixedPoint.Unsigned memory);\n}\n" + }, + "@uma/core/contracts/merkle-distributor/implementation/MerkleDistributor.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./MerkleDistributorInterface.sol\";\n\n/**\n * Inspired by:\n * - https://github.com/pie-dao/vested-token-migration-app\n * - https://github.com/Uniswap/merkle-distributor\n * - https://github.com/balancer-labs/erc20-redeemable\n *\n * @title MerkleDistributor contract.\n * @notice Allows an owner to distribute any reward ERC20 to claimants according to Merkle roots. The owner can specify\n * multiple Merkle roots distributions with customized reward currencies.\n * @dev The Merkle trees are not validated in any way, so the system assumes the contract owner behaves honestly.\n */\ncontract MerkleDistributor is MerkleDistributorInterface, Ownable {\n using SafeERC20 for IERC20;\n\n // Windows are mapped to arbitrary indices.\n mapping(uint256 => Window) public merkleWindows;\n\n // Index of next created Merkle root.\n uint256 public nextCreatedIndex;\n\n // Track which accounts have claimed for each window index.\n // Note: uses a packed array of bools for gas optimization on tracking certain claims. Copied from Uniswap's contract.\n mapping(uint256 => mapping(uint256 => uint256)) private claimedBitMap;\n\n /****************************************\n * EVENTS\n ****************************************/\n event Claimed(\n address indexed caller,\n uint256 windowIndex,\n address indexed account,\n uint256 accountIndex,\n uint256 amount,\n address indexed rewardToken\n );\n event CreatedWindow(\n uint256 indexed windowIndex,\n uint256 rewardsDeposited,\n address indexed rewardToken,\n address owner\n );\n event WithdrawRewards(address indexed owner, uint256 amount, address indexed currency);\n event DeleteWindow(uint256 indexed windowIndex, address owner);\n\n /****************************\n * ADMIN FUNCTIONS\n ****************************/\n\n /**\n * @notice Set merkle root for the next available window index and seed allocations.\n * @notice Callable only by owner of this contract. Caller must have approved this contract to transfer\n * `rewardsToDeposit` amount of `rewardToken` or this call will fail. Importantly, we assume that the\n * owner of this contract correctly chooses an amount `rewardsToDeposit` that is sufficient to cover all\n * claims within the `merkleRoot`.\n * @param rewardsToDeposit amount of rewards to deposit to seed this allocation.\n * @param rewardToken ERC20 reward token.\n * @param merkleRoot merkle root describing allocation.\n * @param ipfsHash hash of IPFS object, conveniently stored for clients\n */\n function setWindow(\n uint256 rewardsToDeposit,\n address rewardToken,\n bytes32 merkleRoot,\n string calldata ipfsHash\n ) external onlyOwner {\n uint256 indexToSet = nextCreatedIndex;\n nextCreatedIndex = indexToSet + 1;\n\n _setWindow(indexToSet, rewardsToDeposit, rewardToken, merkleRoot, ipfsHash);\n }\n\n /**\n * @notice Delete merkle root at window index.\n * @dev Callable only by owner. Likely to be followed by a withdrawRewards call to clear contract state.\n * @param windowIndex merkle root index to delete.\n */\n function deleteWindow(uint256 windowIndex) external onlyOwner {\n delete merkleWindows[windowIndex];\n emit DeleteWindow(windowIndex, msg.sender);\n }\n\n /**\n * @notice Emergency method that transfers rewards out of the contract if the contract was configured improperly.\n * @dev Callable only by owner.\n * @param rewardCurrency rewards to withdraw from contract.\n * @param amount amount of rewards to withdraw.\n */\n function withdrawRewards(IERC20 rewardCurrency, uint256 amount) external onlyOwner {\n rewardCurrency.safeTransfer(msg.sender, amount);\n emit WithdrawRewards(msg.sender, amount, address(rewardCurrency));\n }\n\n /****************************\n * NON-ADMIN FUNCTIONS\n ****************************/\n\n /**\n * @notice Batch claims to reduce gas versus individual submitting all claims. Method will fail\n * if any individual claims within the batch would fail.\n * @dev Optimistically tries to batch together consecutive claims for the same account and same\n * reward token to reduce gas. Therefore, the most gas-cost-optimal way to use this method\n * is to pass in an array of claims sorted by account and reward currency. It also reverts\n * when any of individual `_claim`'s `amount` exceeds `remainingAmount` for its window.\n * @param claims array of claims to claim.\n */\n function claimMulti(Claim[] memory claims) public virtual override {\n uint256 batchedAmount;\n uint256 claimCount = claims.length;\n for (uint256 i = 0; i < claimCount; i++) {\n Claim memory _claim = claims[i];\n _verifyAndMarkClaimed(_claim);\n batchedAmount += _claim.amount;\n\n // If the next claim is NOT the same account or the same token (or this claim is the last one),\n // then disburse the `batchedAmount` to the current claim's account for the current claim's reward token.\n uint256 nextI = i + 1;\n IERC20 currentRewardToken = merkleWindows[_claim.windowIndex].rewardToken;\n if (\n nextI == claimCount ||\n // This claim is last claim.\n claims[nextI].account != _claim.account ||\n // Next claim account is different than current one.\n merkleWindows[claims[nextI].windowIndex].rewardToken != currentRewardToken\n // Next claim reward token is different than current one.\n ) {\n currentRewardToken.safeTransfer(_claim.account, batchedAmount);\n batchedAmount = 0;\n }\n }\n }\n\n /**\n * @notice Claim amount of reward tokens for account, as described by Claim input object.\n * @dev If the `_claim`'s `amount`, `accountIndex`, and `account` do not exactly match the\n * values stored in the merkle root for the `_claim`'s `windowIndex` this method\n * will revert. It also reverts when `_claim`'s `amount` exceeds `remainingAmount` for the window.\n * @param _claim claim object describing amount, accountIndex, account, window index, and merkle proof.\n */\n function claim(Claim memory _claim) public virtual override {\n _verifyAndMarkClaimed(_claim);\n merkleWindows[_claim.windowIndex].rewardToken.safeTransfer(_claim.account, _claim.amount);\n }\n\n /**\n * @notice Returns True if the claim for `accountIndex` has already been completed for the Merkle root at\n * `windowIndex`.\n * @dev This method will only work as intended if all `accountIndex`'s are unique for a given `windowIndex`.\n * The onus is on the Owner of this contract to submit only valid Merkle roots.\n * @param windowIndex merkle root to check.\n * @param accountIndex account index to check within window index.\n * @return True if claim has been executed already, False otherwise.\n */\n function isClaimed(uint256 windowIndex, uint256 accountIndex) public view returns (bool) {\n uint256 claimedWordIndex = accountIndex / 256;\n uint256 claimedBitIndex = accountIndex % 256;\n uint256 claimedWord = claimedBitMap[windowIndex][claimedWordIndex];\n uint256 mask = (1 << claimedBitIndex);\n return claimedWord & mask == mask;\n }\n\n /**\n * @notice Returns rewardToken set by admin for windowIndex.\n * @param windowIndex merkle root to check.\n * @return address Reward token address\n */\n function getRewardTokenForWindow(uint256 windowIndex) public view override returns (address) {\n return address(merkleWindows[windowIndex].rewardToken);\n }\n\n /**\n * @notice Returns True if leaf described by {account, amount, accountIndex} is stored in Merkle root at given\n * window index.\n * @param _claim claim object describing amount, accountIndex, account, window index, and merkle proof.\n * @return valid True if leaf exists.\n */\n function verifyClaim(Claim memory _claim) public view returns (bool valid) {\n bytes32 leaf = keccak256(abi.encodePacked(_claim.account, _claim.amount, _claim.accountIndex));\n return MerkleProof.verify(_claim.merkleProof, merkleWindows[_claim.windowIndex].merkleRoot, leaf);\n }\n\n /****************************\n * PRIVATE FUNCTIONS\n ****************************/\n\n // Mark claim as completed for `accountIndex` for Merkle root at `windowIndex`.\n function _setClaimed(uint256 windowIndex, uint256 accountIndex) private {\n uint256 claimedWordIndex = accountIndex / 256;\n uint256 claimedBitIndex = accountIndex % 256;\n claimedBitMap[windowIndex][claimedWordIndex] =\n claimedBitMap[windowIndex][claimedWordIndex] |\n (1 << claimedBitIndex);\n }\n\n // Store new Merkle root at `windowindex`. Pull `rewardsDeposited` from caller to seed distribution for this root.\n function _setWindow(\n uint256 windowIndex,\n uint256 rewardsDeposited,\n address rewardToken,\n bytes32 merkleRoot,\n string memory ipfsHash\n ) private {\n Window storage window = merkleWindows[windowIndex];\n window.merkleRoot = merkleRoot;\n window.remainingAmount = rewardsDeposited;\n window.rewardToken = IERC20(rewardToken);\n window.ipfsHash = ipfsHash;\n\n emit CreatedWindow(windowIndex, rewardsDeposited, rewardToken, msg.sender);\n\n window.rewardToken.safeTransferFrom(msg.sender, address(this), rewardsDeposited);\n }\n\n // Verify claim is valid and mark it as completed in this contract.\n function _verifyAndMarkClaimed(Claim memory _claim) internal {\n // Check claimed proof against merkle window at given index.\n require(verifyClaim(_claim), \"Incorrect merkle proof\");\n // Check the account has not yet claimed for this window.\n require(!isClaimed(_claim.windowIndex, _claim.accountIndex), \"Account has already claimed for this window\");\n\n // Proof is correct and claim has not occurred yet, mark claimed complete.\n _setClaimed(_claim.windowIndex, _claim.accountIndex);\n merkleWindows[_claim.windowIndex].remainingAmount -= _claim.amount;\n emit Claimed(\n msg.sender,\n _claim.windowIndex,\n _claim.account,\n _claim.accountIndex,\n _claim.amount,\n address(merkleWindows[_claim.windowIndex].rewardToken)\n );\n }\n}\n" + }, + "@uma/core/contracts/merkle-distributor/implementation/MerkleDistributorInterface.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @notice Concise list of functions in MerkleDistributor implementation that would be called by\n * a consuming external contract (such as the Across Protocol's AcceleratingDistributor).\n */\ninterface MerkleDistributorInterface {\n // A Window maps a Merkle root to a reward token address.\n struct Window {\n // Merkle root describing the distribution.\n bytes32 merkleRoot;\n // Remaining amount of deposited rewards that have not yet been claimed.\n uint256 remainingAmount;\n // Currency in which reward is processed.\n IERC20 rewardToken;\n // IPFS hash of the merkle tree. Can be used to independently fetch recipient proofs and tree. Note that the canonical\n // data type for storing an IPFS hash is a multihash which is the concatenation of \n // . We opted to store this in a string type to make it easier\n // for users to query the ipfs data without needing to reconstruct the multihash. to view the IPFS data simply\n // go to https://cloudflare-ipfs.com/ipfs/.\n string ipfsHash;\n }\n\n // Represents an account's claim for `amount` within the Merkle root located at the `windowIndex`.\n struct Claim {\n uint256 windowIndex;\n uint256 amount;\n uint256 accountIndex; // Used only for bitmap. Assumed to be unique for each claim.\n address account;\n bytes32[] merkleProof;\n }\n\n function claim(Claim memory _claim) external;\n\n function claimMulti(Claim[] memory claims) external;\n\n function getRewardTokenForWindow(uint256 windowIndex) external view returns (address);\n}\n" + }, + "@uma/core/contracts/optimistic-oracle-v2/interfaces/OptimisticOracleInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"../../data-verification-mechanism/interfaces/FinderInterface.sol\";\n\n/**\n * @title Financial contract facing Oracle interface.\n * @dev Interface used by financial contracts to interact with the Oracle. Voters will use a different interface.\n */\nabstract contract OptimisticOracleInterface {\n event RequestPrice(\n address indexed requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes ancillaryData,\n address currency,\n uint256 reward,\n uint256 finalFee\n );\n event ProposePrice(\n address indexed requester,\n address indexed proposer,\n bytes32 identifier,\n uint256 timestamp,\n bytes ancillaryData,\n int256 proposedPrice,\n uint256 expirationTimestamp,\n address currency\n );\n event DisputePrice(\n address indexed requester,\n address indexed proposer,\n address indexed disputer,\n bytes32 identifier,\n uint256 timestamp,\n bytes ancillaryData,\n int256 proposedPrice\n );\n event Settle(\n address indexed requester,\n address indexed proposer,\n address indexed disputer,\n bytes32 identifier,\n uint256 timestamp,\n bytes ancillaryData,\n int256 price,\n uint256 payout\n );\n\n // Struct representing the state of a price request.\n enum State {\n Invalid, // Never requested.\n Requested, // Requested, no other actions taken.\n Proposed, // Proposed, but not expired or disputed yet.\n Expired, // Proposed, not disputed, past liveness.\n Disputed, // Disputed, but no DVM price returned yet.\n Resolved, // Disputed and DVM price is available.\n Settled // Final price has been set in the contract (can get here from Expired or Resolved).\n }\n\n // Struct representing a price request.\n struct Request {\n address proposer; // Address of the proposer.\n address disputer; // Address of the disputer.\n IERC20 currency; // ERC20 token used to pay rewards and fees.\n bool settled; // True if the request is settled.\n bool refundOnDispute; // True if the requester should be refunded their reward on dispute.\n int256 proposedPrice; // Price that the proposer submitted.\n int256 resolvedPrice; // Price resolved once the request is settled.\n uint256 expirationTime; // Time at which the request auto-settles without a dispute.\n uint256 reward; // Amount of the currency to pay to the proposer on settlement.\n uint256 finalFee; // Final fee to pay to the Store upon request to the DVM.\n uint256 bond; // Bond that the proposer and disputer must pay on top of the final fee.\n uint256 customLiveness; // Custom liveness value set by the requester.\n }\n\n // This value must be <= the Voting contract's `ancillaryBytesLimit` value otherwise it is possible\n // that a price can be requested to this contract successfully, but cannot be disputed because the DVM refuses\n // to accept a price request made with ancillary data length over a certain size.\n uint256 public constant ancillaryBytesLimit = 8192;\n\n function defaultLiveness() external view virtual returns (uint256);\n\n function finder() external view virtual returns (FinderInterface);\n\n function getCurrentTime() external view virtual returns (uint256);\n\n // Note: this is required so that typechain generates a return value with named fields.\n mapping(bytes32 => Request) public requests;\n\n /**\n * @notice Requests a new price.\n * @param identifier price identifier being requested.\n * @param timestamp timestamp of the price being requested.\n * @param ancillaryData ancillary data representing additional args being passed with the price request.\n * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM.\n * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0,\n * which could make sense if the contract requests and proposes the value in the same call or\n * provides its own reward system.\n * @return totalBond default bond (final fee) + final fee that the proposer and disputer will be required to pay.\n * This can be changed with a subsequent call to setBond().\n */\n function requestPrice(\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData,\n IERC20 currency,\n uint256 reward\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Set the proposal bond associated with a price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param bond custom bond amount to set.\n * @return totalBond new bond + final fee that the proposer and disputer will be required to pay. This can be\n * changed again with a subsequent call to setBond().\n */\n function setBond(\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData,\n uint256 bond\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Sets the request to refund the reward if the proposal is disputed. This can help to \"hedge\" the caller\n * in the event of a dispute-caused delay. Note: in the event of a dispute, the winner still receives the other's\n * bond, so there is still profit to be made even if the reward is refunded.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n */\n function setRefundOnDispute(\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) external virtual;\n\n /**\n * @notice Sets a custom liveness value for the request. Liveness is the amount of time a proposal must wait before\n * being auto-resolved.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param customLiveness new custom liveness.\n */\n function setCustomLiveness(\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData,\n uint256 customLiveness\n ) external virtual;\n\n /**\n * @notice Proposes a price value on another address' behalf. Note: this address will receive any rewards that come\n * from this proposal. However, any bonds are pulled from the caller.\n * @param proposer address to set as the proposer.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param proposedPrice price being proposed.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the proposer once settled if the proposal is correct.\n */\n function proposePriceFor(\n address proposer,\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData,\n int256 proposedPrice\n ) public virtual returns (uint256 totalBond);\n\n /**\n * @notice Proposes a price value for an existing price request.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param proposedPrice price being proposed.\n * @return totalBond the amount that's pulled from the proposer's wallet as a bond. The bond will be returned to\n * the proposer once settled if the proposal is correct.\n */\n function proposePrice(\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData,\n int256 proposedPrice\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Disputes a price request with an active proposal on another address' behalf. Note: this address will\n * receive any rewards that come from this dispute. However, any bonds are pulled from the caller.\n * @param disputer address to set as the disputer.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the disputer once settled if the dispute was value (the proposal was incorrect).\n */\n function disputePriceFor(\n address disputer,\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) public virtual returns (uint256 totalBond);\n\n /**\n * @notice Disputes a price value for an existing price request with an active proposal.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return totalBond the amount that's pulled from the disputer's wallet as a bond. The bond will be returned to\n * the disputer once settled if the dispute was valid (the proposal was incorrect).\n */\n function disputePrice(\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Retrieves a price that was previously requested by a caller. Reverts if the request is not settled\n * or settleable. Note: this method is not view so that this call may actually settle the price request if it\n * hasn't been settled.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return resolved price.\n */\n function settleAndGetPrice(\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) external virtual returns (int256);\n\n /**\n * @notice Attempts to settle an outstanding price request. Will revert if it isn't settleable.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return payout the amount that the \"winner\" (proposer or disputer) receives on settlement. This amount includes\n * the returned bonds as well as additional rewards.\n */\n function settle(\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) external virtual returns (uint256 payout);\n\n /**\n * @notice Gets the current data structure containing all information about a price request.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return the Request data structure.\n */\n function getRequest(\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) public view virtual returns (Request memory);\n\n /**\n * @notice Returns the state of a price request.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return the State enum value.\n */\n function getState(\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) public view virtual returns (State);\n\n /**\n * @notice Checks if a given request has resolved or been settled (i.e the optimistic oracle has a price).\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @return true if price has resolved or settled, false otherwise.\n */\n function hasPrice(\n address requester,\n bytes32 identifier,\n uint256 timestamp,\n bytes memory ancillaryData\n ) public view virtual returns (bool);\n\n function stampAncillaryData(bytes memory ancillaryData, address requester)\n public\n view\n virtual\n returns (bytes memory);\n}\n" + }, + "@uma/core/contracts/optimistic-oracle-v2/interfaces/SkinnyOptimisticOracleInterface.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"../interfaces/OptimisticOracleInterface.sol\";\n\n/**\n * @title Interface for the gas-cost-reduced version of the OptimisticOracle.\n * @notice Differences from normal OptimisticOracle:\n * - refundOnDispute: flag is removed, by default there are no refunds on disputes.\n * - customizing request parameters: In the OptimisticOracle, parameters like `bond` and `customLiveness` can be reset\n * after a request is already made via `requestPrice`. In the SkinnyOptimisticOracle, these parameters can only be\n * set in `requestPrice`, which has an expanded input set.\n * - settleAndGetPrice: Replaced by `settle`, which can only be called once per settleable request. The resolved price\n * can be fetched via the `Settle` event or the return value of `settle`.\n * - general changes to interface: Functions that interact with existing requests all require the parameters of the\n * request to modify to be passed as input. These parameters must match with the existing request parameters or the\n * function will revert. This change reflects the internal refactor to store hashed request parameters instead of the\n * full request struct.\n * @dev Interface used by financial contracts to interact with the Oracle. Voters will use a different interface.\n */\nabstract contract SkinnyOptimisticOracleInterface {\n // Struct representing a price request. Note that this differs from the OptimisticOracleInterface's Request struct\n // in that refundOnDispute is removed.\n struct Request {\n address proposer; // Address of the proposer.\n address disputer; // Address of the disputer.\n IERC20 currency; // ERC20 token used to pay rewards and fees.\n bool settled; // True if the request is settled.\n int256 proposedPrice; // Price that the proposer submitted.\n int256 resolvedPrice; // Price resolved once the request is settled.\n uint256 expirationTime; // Time at which the request auto-settles without a dispute.\n uint256 reward; // Amount of the currency to pay to the proposer on settlement.\n uint256 finalFee; // Final fee to pay to the Store upon request to the DVM.\n uint256 bond; // Bond that the proposer and disputer must pay on top of the final fee.\n uint256 customLiveness; // Custom liveness value set by the requester.\n }\n\n // This value must be <= the Voting contract's `ancillaryBytesLimit` value otherwise it is possible\n // that a price can be requested to this contract successfully, but cannot be disputed because the DVM refuses\n // to accept a price request made with ancillary data length over a certain size.\n uint256 public constant ancillaryBytesLimit = 8192;\n\n /**\n * @notice Requests a new price.\n * @param identifier price identifier being requested.\n * @param timestamp timestamp of the price being requested.\n * @param ancillaryData ancillary data representing additional args being passed with the price request.\n * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM.\n * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0,\n * which could make sense if the contract requests and proposes the value in the same call or\n * provides its own reward system.\n * @param bond custom proposal bond to set for request. If set to 0, defaults to the final fee.\n * @param customLiveness custom proposal liveness to set for request.\n * @return totalBond default bond + final fee that the proposer and disputer will be required to pay.\n */\n function requestPrice(\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n IERC20 currency,\n uint256 reward,\n uint256 bond,\n uint256 customLiveness\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Proposes a price value on another address' behalf. Note: this address will receive any rewards that come\n * from this proposal. However, any bonds are pulled from the caller.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters whose hash must match the request that the caller wants to\n * propose a price for.\n * @param proposer address to set as the proposer.\n * @param proposedPrice price being proposed.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the proposer once settled if the proposal is correct.\n */\n function proposePriceFor(\n address requester,\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request,\n address proposer,\n int256 proposedPrice\n ) public virtual returns (uint256 totalBond);\n\n /**\n * @notice Proposes a price value where caller is the proposer.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters whose hash must match the request that the caller wants to\n * propose a price for.\n * @param proposedPrice price being proposed.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the proposer once settled if the proposal is correct.\n */\n function proposePrice(\n address requester,\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request,\n int256 proposedPrice\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Combines logic of requestPrice and proposePrice while taking advantage of gas savings from not having to\n * overwrite Request params that a normal requestPrice() => proposePrice() flow would entail. Note: The proposer\n * will receive any rewards that come from this proposal. However, any bonds are pulled from the caller.\n * @dev The caller is the requester, but the proposer can be customized.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param currency ERC20 token used for payment of rewards and fees. Must be approved for use with the DVM.\n * @param reward reward offered to a successful proposer. Will be pulled from the caller. Note: this can be 0,\n * which could make sense if the contract requests and proposes the value in the same call or\n * provides its own reward system.\n * @param bond custom proposal bond to set for request. If set to 0, defaults to the final fee.\n * @param customLiveness custom proposal liveness to set for request.\n * @param proposer address to set as the proposer.\n * @param proposedPrice price being proposed.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the proposer once settled if the proposal is correct.\n */\n function requestAndProposePriceFor(\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n IERC20 currency,\n uint256 reward,\n uint256 bond,\n uint256 customLiveness,\n address proposer,\n int256 proposedPrice\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Disputes a price request with an active proposal on another address' behalf. Note: this address will\n * receive any rewards that come from this dispute. However, any bonds are pulled from the caller.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters whose hash must match the request that the caller wants to\n * dispute.\n * @param disputer address to set as the disputer.\n * @param requester sender of the initial price request.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the disputer once settled if the dispute was valid (the proposal was incorrect).\n */\n function disputePriceFor(\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request,\n address disputer,\n address requester\n ) public virtual returns (uint256 totalBond);\n\n /**\n * @notice Disputes a price request with an active proposal where caller is the disputer.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters whose hash must match the request that the caller wants to\n * dispute.\n * @return totalBond the amount that's pulled from the caller's wallet as a bond. The bond will be returned to\n * the disputer once settled if the dispute was valid (the proposal was incorrect).\n */\n function disputePrice(\n address requester,\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request\n ) external virtual returns (uint256 totalBond);\n\n /**\n * @notice Attempts to settle an outstanding price request. Will revert if it isn't settleable.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters whose hash must match the request that the caller wants to\n * settle.\n * @return payout the amount that the \"winner\" (proposer or disputer) receives on settlement. This amount includes\n * the returned bonds as well as additional rewards.\n * @return resolvedPrice the price that the request settled to.\n */\n function settle(\n address requester,\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request\n ) external virtual returns (uint256 payout, int256 resolvedPrice);\n\n /**\n * @notice Computes the current state of a price request. See the State enum for more details.\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters.\n * @return the State.\n */\n function getState(\n address requester,\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request\n ) external virtual returns (OptimisticOracleInterface.State);\n\n /**\n * @notice Checks if a given request has resolved, expired or been settled (i.e the optimistic oracle has a price).\n * @param requester sender of the initial price request.\n * @param identifier price identifier to identify the existing request.\n * @param timestamp timestamp to identify the existing request.\n * @param ancillaryData ancillary data of the price being requested.\n * @param request price request parameters. The hash of these parameters must match with the request hash that is\n * associated with the price request unique ID {requester, identifier, timestamp, ancillaryData}, or this method\n * will revert.\n * @return boolean indicating true if price exists and false if not.\n */\n function hasPrice(\n address requester,\n bytes32 identifier,\n uint32 timestamp,\n bytes memory ancillaryData,\n Request memory request\n ) public virtual returns (bool);\n\n /**\n * @notice Generates stamped ancillary data in the format that it would be used in the case of a price dispute.\n * @param ancillaryData ancillary data of the price being requested.\n * @param requester sender of the initial price request.\n * @return the stamped ancillary bytes.\n */\n function stampAncillaryData(bytes memory ancillaryData, address requester)\n public\n pure\n virtual\n returns (bytes memory);\n}\n" + }, + "contracts/AcrossConfigStore.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"@uma/core/contracts/common/implementation/MultiCaller.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Allows admin to set and update configuration settings for full contract system. These settings are designed\n * to be consumed by off-chain bots, rather than by other contracts.\n * @dev This contract should not perform any validation on the setting values and should be owned by the governance\n * system of the full contract suite.\n * @custom:security-contact bugs@across.to\n */\ncontract AcrossConfigStore is Ownable, MultiCaller {\n // General dictionary where admin can associate variables with specific L1 tokens, like the Rate Model and Token\n // Transfer Thresholds.\n mapping(address => string) public l1TokenConfig;\n\n // General dictionary where admin can store global variables like `MAX_POOL_REBALANCE_LEAF_SIZE` and\n // `MAX_RELAYER_REPAYMENT_LEAF_SIZE` that off-chain agents can query.\n mapping(bytes32 => string) public globalConfig;\n\n event UpdatedTokenConfig(address indexed key, string value);\n event UpdatedGlobalConfig(bytes32 indexed key, string value);\n\n /**\n * @notice Updates token config.\n * @param l1Token the l1 token address to update value for.\n * @param value Value to update.\n */\n function updateTokenConfig(address l1Token, string memory value) external onlyOwner {\n l1TokenConfig[l1Token] = value;\n emit UpdatedTokenConfig(l1Token, value);\n }\n\n /**\n * @notice Updates global config.\n * @param key Key to update.\n * @param value Value to update.\n */\n function updateGlobalConfig(bytes32 key, string calldata value) external onlyOwner {\n globalConfig[key] = value;\n emit UpdatedGlobalConfig(key, value);\n }\n}\n" + }, + "contracts/Base_SpokePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\nimport \"@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol\";\n\nimport \"./Ovm_SpokePool.sol\";\nimport \"./external/interfaces/CCTPInterfaces.sol\";\n\n/**\n * @notice Base Spoke pool.\n * @custom:security-contact bugs@across.to\n */\ncontract Base_SpokePool is Ovm_SpokePool {\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeTokenAddress,\n uint32 _depositQuoteTimeBuffer,\n uint32 _fillDeadlineBuffer,\n IERC20 _l2Usdc,\n ITokenMessenger _cctpTokenMessenger\n )\n Ovm_SpokePool(\n _wrappedNativeTokenAddress,\n _depositQuoteTimeBuffer,\n _fillDeadlineBuffer,\n _l2Usdc,\n _cctpTokenMessenger\n )\n {} // solhint-disable-line no-empty-blocks\n\n /**\n * @notice Construct the OVM Base SpokePool.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n */\n function initialize(\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool\n ) public initializer {\n __OvmSpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool, Lib_PredeployAddresses.OVM_ETH);\n }\n}\n" + }, + "contracts/Blast_DaiRetriever.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./Lockable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@uma/core/contracts/common/implementation/MultiCaller.sol\";\n\ninterface USDYieldManager {\n function claimWithdrawal(uint256 _requestId, uint256 _hintId) external returns (bool success);\n}\n\n/**\n * @notice Contract deployed on Ethereum to facilitate DAI transfers from Blast to the HubPool.\n * @dev Blast USDB withdrawals are a two step process where the L2 to L1 withdrawal must first be finalized via\n * the typical OP Stack mechanism, and then a claim from the withdrawal's *recipient* must be made against a\n * USDBYieldManager contract. This means that the Blast_SpokePool must set its recipient to this contract's address\n * and then an EOA can call this contract to retrieve the DAI.\n */\ncontract Blast_DaiRetriever is Lockable, MultiCaller {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n // Should be set to HubPool on Ethereum\n address public immutable hubPool;\n\n // USDCYieldManager contract on Ethereum which releases DAI to the hubPool.\n USDYieldManager public immutable usdYieldManager;\n\n // Token to be retrieved.\n IERC20Upgradeable public immutable dai;\n\n /**\n * @notice Constructs USDB Retriever\n * @param _hubPool Where to send DAI to.\n * @param _usdYieldManager USDCYieldManager contract on Ethereum.\n * @param _dai DAI token to be retrieved.\n */\n constructor(\n address _hubPool,\n USDYieldManager _usdYieldManager,\n IERC20Upgradeable _dai\n ) {\n //slither-disable-next-line missing-zero-check\n hubPool = _hubPool;\n usdYieldManager = _usdYieldManager;\n dai = _dai;\n }\n\n /**\n * @notice Calls USDCYieldManager contract to release DAI and send to the hubPool. Required to use this function\n * to retrieve DAI since only the L2 withdrawal recipient can make this call.\n * @notice This can revert if the claim is not ready yet. It takes ~12 hours for a Blast admin to make the DAI\n * available for retrieval following withdrawal finalization.\n * @param _requestId L2 withdrawal request ID. Emitted in L1 WithdrawalRequested event when the L2 to L1\n * withdrawal is first \"finalized\" but still awaiting the recipient to claim the DAI.\n * @param _hintId Checkpoint hint ID. Can be found by querying USDYieldManager.findCheckpointHint.\n */\n function retrieve(uint256 _requestId, uint256 _hintId) public nonReentrant {\n require(usdYieldManager.claimWithdrawal(_requestId, _hintId), \"claim failed\");\n dai.safeTransfer(hubPool, dai.balanceOf(address(this)));\n }\n}\n" + }, + "contracts/Boba_SpokePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./Ovm_SpokePool.sol\";\n\n/**\n * @notice Boba Spoke pool. Note that the l2ETH and l2WETH are the opposite as that in Optimism.\n */\ncontract Boba_SpokePool is Ovm_SpokePool {\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeTokenAddress,\n uint32 _depositQuoteTimeBuffer,\n uint32 _fillDeadlineBuffer\n )\n Ovm_SpokePool(\n _wrappedNativeTokenAddress,\n _depositQuoteTimeBuffer,\n _fillDeadlineBuffer,\n IERC20(address(0)),\n ITokenMessenger(address(0))\n )\n {} // solhint-disable-line no-empty-blocks\n\n /**\n * @notice Construct the OVM Boba SpokePool.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n */\n function initialize(\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool\n ) public initializer {\n __OvmSpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool, 0x4200000000000000000000000000000000000006);\n }\n}\n" + }, + "contracts/BondToken.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport \"./interfaces/HubPoolInterface.sol\";\nimport \"./external/WETH9.sol\";\n\ninterface ExtendedHubPoolInterface is HubPoolInterface {\n // Specify the automatically-implemented rootBundleProposal() getter.\n function rootBundleProposal() external pure returns (HubPoolInterface.RootBundle memory);\n}\n\n/**\n * @notice Across Bond Token (ABT).\n * ABT is a simple deposit contract based on WETH9. ABT is issued proportionally to any address that deposits Ether. It\n * imposes address-based permissioning on the WETH9 transferFrom() function in order to constrain the movement of ABT\n * into the Across v2 HubPool contract. When configured as the required HubPool bond token, ABT can dramatically reduce\n * the attack surface of the HubPool by requiring that addresses are explicitly approved before they can successfully\n * submit a root bundle proposal. The address-based permissioning does not constrain transfers that are needed to dispute\n * a root bundle proposal, so the ability of decentralised/unknown actors to dispute is unaffected.\n * @custom:security-contact bugs@across.to\n */\ncontract BondToken is WETH9, Ownable {\n using Address for address;\n\n ExtendedHubPoolInterface public immutable HUB_POOL;\n\n /**\n * @notice Addresses that are permitted to make HubPool root bundle proposals.\n */\n mapping(address => bool) public proposers;\n\n /**\n * @notice Emitted on proposer permissions update.\n */\n event ProposerModified(address proposer, bool enabled);\n\n /**\n * @notice BondToken constructor.\n * @param _hubPool Address of the target HubPool contract.\n */\n constructor(ExtendedHubPoolInterface _hubPool) {\n name = \"Across Bond Token\";\n symbol = \"ABT\";\n HUB_POOL = _hubPool;\n }\n\n /**\n * @notice Enable or disable an address as an allowed proposer. Emits a \"ProposerModified\" event on completion.\n * @param proposer Proposer address to modify.\n * @param enabled Boolean controlling whether the address is permitted to propose.\n */\n function setProposer(address proposer, bool enabled) external onlyOwner {\n proposers[proposer] = enabled;\n emit ProposerModified(proposer, enabled);\n }\n\n /**\n * @notice Transfer amt from src to dst. Prevents unauthorised root bundle proposals by blocking transfers to the\n * HubPool under the following conditions:\n * - The src address is not a pre-approved proposer, *and*\n * - The src address is the current proposer of a HubPool root bundle.\n * Falls back to the base implementation after verifying that the transfer is permitted.\n * @dev The require(..., \"Transfer not permitted\") statement is dependent on the internal ordering of HubPool\n * proposedRootBundle state variable updates, relative to calling bondToken.safeTransferFrom(). Changing the order\n * of HubPool actions may invalidate this verification. BondToken tests are implemented to detect this.\n * @param src Source address.\n * @param dst Destination address.\n * @param amt Amount to transfer.\n * @return True on success.\n */\n function transferFrom(\n address src,\n address dst,\n uint256 amt\n ) public override returns (bool) {\n if (dst == address(HUB_POOL)) {\n require(proposers[src] || HUB_POOL.rootBundleProposal().proposer != src, \"Transfer not permitted\");\n }\n return super.transferFrom(src, dst, amt);\n }\n}\n" + }, + "contracts/chain-adapters/Arbitrum_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"../external/interfaces/CCTPInterfaces.sol\";\nimport \"../libraries/CircleCCTPAdapter.sol\";\n\n/**\n * @notice Interface for Arbitrum's L1 Inbox contract used to send messages to Arbitrum.\n * @custom:security-contact bugs@across.to\n */\ninterface ArbitrumL1InboxLike {\n /**\n * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts\n * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error\n * @dev Caller must set msg.value equal to at least `maxSubmissionCost + maxGas * gasPriceBid`.\n * all msg.value will deposited to callValueRefundAddress on L2\n * @dev More details can be found here: https://developer.arbitrum.io/arbos/l1-to-l2-messaging\n * @param to destination L2 contract address\n * @param l2CallValue call value for retryable L2 message\n * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee\n * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance\n * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled\n * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\n * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\n * @param data ABI encoded data of L2 message\n * @return unique message number of the retryable transaction\n */\n function createRetryableTicket(\n address to,\n uint256 l2CallValue,\n uint256 maxSubmissionCost,\n address excessFeeRefundAddress,\n address callValueRefundAddress,\n uint256 gasLimit,\n uint256 maxFeePerGas,\n bytes calldata data\n ) external payable returns (uint256);\n\n /**\n * @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts\n * @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed\n * funds come from the deposit alone, rather than falling back on the user's L2 balance\n * @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress).\n * createRetryableTicket method is the recommended standard.\n * @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error\n * @param to destination L2 contract address\n * @param l2CallValue call value for retryable L2 message\n * @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee\n * @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance\n * @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled\n * @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\n * @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)\n * @param data ABI encoded data of L2 message\n * @return unique message number of the retryable transaction\n */\n function unsafeCreateRetryableTicket(\n address to,\n uint256 l2CallValue,\n uint256 maxSubmissionCost,\n address excessFeeRefundAddress,\n address callValueRefundAddress,\n uint256 gasLimit,\n uint256 maxFeePerGas,\n bytes calldata data\n ) external payable returns (uint256);\n}\n\n/**\n * @notice Layer 1 Gateway contract for bridging standard ERC20s to Arbitrum.\n */\ninterface ArbitrumL1ERC20GatewayLike {\n /**\n * @notice Deprecated in favor of outboundTransferCustomRefund but still used in custom bridges\n * like the DAI bridge.\n * @dev Refunded to aliased L2 address of sender if sender has code on L1, otherwise to to sender's EOA on L2.\n * @param _l1Token L1 address of ERC20\n * @param _to Account to be credited with the tokens in the L2 (can be the user's L2 account or a contract),\n * not subject to L2 aliasing. This account, or its L2 alias if it have code in L1, will also be able to\n * cancel the retryable ticket and receive callvalue refund\n * @param _amount Token Amount\n * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution\n * @param _gasPriceBid Gas price for L2 execution\n * @param _data encoded data from router and user\n * @return res abi encoded inbox sequence number\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory);\n\n /**\n * @notice Deposit ERC20 token from Ethereum into Arbitrum.\n * @dev L2 address alias will not be applied to the following types of addresses on L1:\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * @param _l1Token L1 address of ERC20\n * @param _refundTo Account, or its L2 alias if it have code in L1, to be credited with excess gas refund in L2\n * @param _to Account to be credited with the tokens in the L2 (can be the user's L2 account or a contract),\n * not subject to L2 aliasing. This account, or its L2 alias if it have code in L1, will also be able to\n * cancel the retryable ticket and receive callvalue refund\n * @param _amount Token Amount\n * @param _maxGas Max gas deducted from user's L2 balance to cover L2 execution\n * @param _gasPriceBid Gas price for L2 execution\n * @param _data encoded data from router and user\n * @return res abi encoded inbox sequence number\n */\n function outboundTransferCustomRefund(\n address _l1Token,\n address _refundTo,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory);\n\n /**\n * @notice get ERC20 gateway for token.\n * @param _token ERC20 address.\n * @return address of ERC20 gateway.\n */\n function getGateway(address _token) external view returns (address);\n}\n\n/**\n * @notice Contract containing logic to send messages from L1 to Arbitrum.\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Arbitrum_Adapter is AdapterInterface, CircleCCTPAdapter {\n using SafeERC20 for IERC20;\n\n // Amount of ETH allocated to pay for the base submission fee. The base submission fee is a parameter unique to\n // retryable transactions; the user is charged the base submission fee to cover the storage costs of keeping their\n // ticket’s calldata in the retry buffer. (current base submission fee is queryable via\n // ArbRetryableTx.getSubmissionPrice). ArbRetryableTicket precompile interface exists at L2 address\n // 0x000000000000000000000000000000000000006E.\n uint256 public constant L2_MAX_SUBMISSION_COST = 0.01e18;\n\n // L2 Gas price bid for immediate L2 execution attempt (queryable via standard eth*gasPrice RPC)\n uint256 public constant L2_GAS_PRICE = 5e9; // 5 gWei\n\n uint256 public constant L2_CALL_VALUE = 0;\n\n uint32 public constant RELAY_TOKENS_L2_GAS_LIMIT = 300_000;\n uint32 public constant RELAY_MESSAGE_L2_GAS_LIMIT = 2_000_000;\n\n address public constant L1_DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n\n // This address on L2 receives extra ETH that is left over after relaying a message via the inbox.\n address public immutable L2_REFUND_L2_ADDRESS;\n\n ArbitrumL1InboxLike public immutable L1_INBOX;\n\n ArbitrumL1ERC20GatewayLike public immutable L1_ERC20_GATEWAY_ROUTER;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1ArbitrumInbox Inbox helper contract to send messages to Arbitrum.\n * @param _l1ERC20GatewayRouter ERC20 gateway router contract to send tokens to Arbitrum.\n * @param _l2RefundL2Address L2 address to receive gas refunds on after a message is relayed.\n * @param _l1Usdc USDC address on L1.\n * @param _cctpTokenMessenger TokenMessenger contract to bridge via CCTP.\n */\n constructor(\n ArbitrumL1InboxLike _l1ArbitrumInbox,\n ArbitrumL1ERC20GatewayLike _l1ERC20GatewayRouter,\n address _l2RefundL2Address,\n IERC20 _l1Usdc,\n ITokenMessenger _cctpTokenMessenger\n ) CircleCCTPAdapter(_l1Usdc, _cctpTokenMessenger, CircleDomainIds.Arbitrum) {\n L1_INBOX = _l1ArbitrumInbox;\n L1_ERC20_GATEWAY_ROUTER = _l1ERC20GatewayRouter;\n L2_REFUND_L2_ADDRESS = _l2RefundL2Address;\n }\n\n /**\n * @notice Send cross-chain message to target on Arbitrum.\n * @notice This contract must hold at least getL1CallValue() amount of ETH to send a message via the Inbox\n * successfully, or the message will get stuck.\n * @param target Contract on Arbitrum that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes memory message) external payable override {\n uint256 requiredL1CallValue = _contractHasSufficientEthBalance(RELAY_MESSAGE_L2_GAS_LIMIT);\n\n L1_INBOX.createRetryableTicket{ value: requiredL1CallValue }(\n target, // destAddr destination L2 contract address\n L2_CALL_VALUE, // l2CallValue call value for retryable L2 message\n L2_MAX_SUBMISSION_COST, // maxSubmissionCost Max gas deducted from user's L2 balance to cover base fee\n L2_REFUND_L2_ADDRESS, // excessFeeRefundAddress maxgas * gasprice - execution cost gets credited here on L2\n L2_REFUND_L2_ADDRESS, // callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled\n RELAY_MESSAGE_L2_GAS_LIMIT, // maxGas Max gas deducted from user's L2 balance to cover L2 execution\n L2_GAS_PRICE, // gasPriceBid price bid for L2 execution\n message // data ABI encoded data of L2 message\n );\n\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Arbitrum.\n * @notice This contract must hold at least getL1CallValue() amount of ETH to send a message via the Inbox\n * successfully, or the message will get stuck.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token, // l2Token is unused for Arbitrum.\n uint256 amount,\n address to\n ) external payable override {\n // Check if this token is USDC, which requires a custom bridge via CCTP.\n if (_isCCTPEnabled() && l1Token == address(usdcToken)) {\n _transferUsdc(to, amount);\n }\n // If not, we can use the Arbitrum gateway\n else {\n uint256 requiredL1CallValue = _contractHasSufficientEthBalance(RELAY_TOKENS_L2_GAS_LIMIT);\n\n // Approve the gateway, not the router, to spend the hub pool's balance. The gateway, which is different\n // per L1 token, will temporarily escrow the tokens to be bridged and pull them from this contract.\n address erc20Gateway = L1_ERC20_GATEWAY_ROUTER.getGateway(l1Token);\n IERC20(l1Token).safeIncreaseAllowance(erc20Gateway, amount);\n\n // `outboundTransfer` expects that the caller includes a bytes message as the last param that includes the\n // maxSubmissionCost to use when creating an L2 retryable ticket: https://github.com/OffchainLabs/arbitrum/blob/e98d14873dd77513b569771f47b5e05b72402c5e/packages/arb-bridge-peripherals/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol#L232\n bytes memory data = abi.encode(L2_MAX_SUBMISSION_COST, \"\");\n\n // Note: Legacy routers don't have the outboundTransferCustomRefund method, so default to using\n // outboundTransfer(). Legacy routers are used for the following tokens that are currently enabled:\n // - DAI: the implementation of `outboundTransfer` at the current DAI custom gateway\n // (https://etherscan.io/address/0xD3B5b60020504bc3489D6949d545893982BA3011#writeContract) sets the\n // sender as the refund address so the aliased HubPool should receive excess funds. Implementation here:\n // https://github.com/makerdao/arbitrum-dai-bridge/blob/11a80385e2622968069c34d401b3d54a59060e87/contracts/l1/L1DaiGateway.sol#L109\n if (l1Token == L1_DAI) {\n // This means that the excess ETH to pay for the L2 transaction will be sent to the aliased\n // contract address on L2, which we'd have to retrieve via a custom adapter, the Arbitrum_RescueAdapter.\n // To do so, in a single transaction: 1) setCrossChainContracts to Arbitrum_RescueAdapter, 2) relayMessage\n // with function data = abi.encode(amountToRescue), 3) setCrossChainContracts back to this adapter.\n L1_ERC20_GATEWAY_ROUTER.outboundTransfer{ value: requiredL1CallValue }(\n l1Token,\n to,\n amount,\n RELAY_TOKENS_L2_GAS_LIMIT,\n L2_GAS_PRICE,\n data\n );\n } else {\n L1_ERC20_GATEWAY_ROUTER.outboundTransferCustomRefund{ value: requiredL1CallValue }(\n l1Token,\n L2_REFUND_L2_ADDRESS,\n to,\n amount,\n RELAY_TOKENS_L2_GAS_LIMIT,\n L2_GAS_PRICE,\n data\n );\n }\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n\n /**\n * @notice Returns required amount of ETH to send a message via the Inbox.\n * @return amount of ETH that this contract needs to hold in order for relayMessage to succeed.\n */\n function getL1CallValue(uint32 l2GasLimit) public pure returns (uint256) {\n return L2_MAX_SUBMISSION_COST + L2_GAS_PRICE * l2GasLimit;\n }\n\n function _contractHasSufficientEthBalance(uint32 l2GasLimit) internal view returns (uint256) {\n uint256 requiredL1CallValue = getL1CallValue(l2GasLimit);\n require(address(this).balance >= requiredL1CallValue, \"Insufficient ETH balance\");\n return requiredL1CallValue;\n }\n}\n" + }, + "contracts/chain-adapters/Arbitrum_RescueAdapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"./Arbitrum_Adapter.sol\"; // Used to import `ArbitrumL1ERC20GatewayLike` and `ArbitrumL1InboxLike`\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice Meant to copy the Arbitrum_Adapter exactly in how it sends L1 --> L2 messages but is designed only to be\n * used by the owner of the HubPool to retrieve ETH held by its aliased address on L2. This ETH builds up because\n * `relayTokens` calls `l1ERC20GatewayRouter.outboundTransfer` which does not allow the caller to specify an L2 refund\n * address the same way that `l1Inbox.createRetryableTicket` does. This means that the alias address of the caller, the\n * HubPool in this case, receives ETH on L2. This Adapter can be used to send messages to Arbitrum specifically to send\n * transactions as if called by the aliased HubPool address.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Arbitrum_RescueAdapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n // Amount of ETH allocated to pay for the base submission fee. The base submission fee is a parameter unique to\n // retryable transactions; the user is charged the base submission fee to cover the storage costs of keeping their\n // ticket’s calldata in the retry buffer. (current base submission fee is queryable via\n // ArbRetryableTx.getSubmissionPrice). ArbRetryableTicket precompile interface exists at L2 address\n // 0x000000000000000000000000000000000000006E.\n uint256 public immutable l2MaxSubmissionCost = 0.01e18;\n\n // L2 Gas price bid for immediate L2 execution attempt (queryable via standard eth*gasPrice RPC)\n uint256 public immutable l2GasPrice = 5e9; // 5 gWei\n\n // Gas limit for immediate L2 execution attempt (can be estimated via NodeInterface.estimateRetryableTicket).\n // NodeInterface precompile interface exists at L2 address 0x00000000000000000000000000000000000000C8\n uint32 public immutable l2GasLimit = 2_000_000;\n\n // This address on L2 receives extra ETH that is left over after relaying a message via the inbox.\n address public immutable l2RefundL2Address;\n\n // L1 HubPool address aliased on L2: https://github.com/OffchainLabs/arbitrum/blob/master/docs/L1_L2_Messages.md#address-aliasing\n address public immutable aliasedL2HubPoolAddress = 0xd297fA914353c44B2e33EBE05F21846f1048CFeB;\n\n ArbitrumL1InboxLike public immutable l1Inbox;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1ArbitrumInbox Inbox helper contract to send messages to Arbitrum.\n */\n constructor(ArbitrumL1InboxLike _l1ArbitrumInbox) {\n l1Inbox = _l1ArbitrumInbox;\n\n l2RefundL2Address = msg.sender;\n }\n\n /**\n * @notice Send cross-chain message to aliased hub pool address on Arbitrum.\n * @notice This contract must hold at least getL1CallValue() amount of ETH to send a message via the Inbox\n * successfully, or the message will get stuck.\n * @param message Data to send to aliased hub pool.\n */\n function relayMessage(address, bytes memory message) external payable override {\n uint256 valueToReturn = abi.decode(message, (uint256));\n\n uint256 requiredL1CallValue = _contractHasSufficientEthBalance();\n\n // In the rescue ETH setup, we send the transaction to the refund address, we provide a call value equal to the\n // amount we want to rescue, and we specify an empty calldata, since it's a simple ETH transfer.\n // Note: we use the unsafe version of createRetryableTicket because it doesn't require the msg.sender to pass\n // in arbTxCallValue in addition to maxSubmissionCost + maxGas * gasPriceBid.\n l1Inbox.unsafeCreateRetryableTicket{ value: requiredL1CallValue }(\n l2RefundL2Address, // destAddr destination L2 contract address\n valueToReturn, // l2CallValue call value for retryable L2 message\n l2MaxSubmissionCost, // maxSubmissionCost Max gas deducted from user's L2 balance to cover base fee\n l2RefundL2Address, // excessFeeRefundAddress maxgas * gasprice - execution cost gets credited here on L2\n l2RefundL2Address, // callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled\n l2GasLimit, // maxGas Max gas deducted from user's L2 balance to cover L2 execution\n l2GasPrice, // gasPriceBid price bid for L2 execution\n \"\" // data ABI encoded data of L2 message\n );\n\n emit MessageRelayed(aliasedL2HubPoolAddress, \"\");\n }\n\n /**\n * @notice Should never be called.\n */\n function relayTokens(\n address,\n address,\n uint256,\n address\n ) external payable override {\n revert(\"useless function\");\n }\n\n /**\n * @notice Returns required amount of ETH to send a message via the Inbox.\n * @return amount of ETH that this contract needs to hold in order for relayMessage to succeed.\n */\n function getL1CallValue() public pure returns (uint256) {\n return l2MaxSubmissionCost + l2GasPrice * l2GasLimit;\n }\n\n function _contractHasSufficientEthBalance() internal view returns (uint256 requiredL1CallValue) {\n requiredL1CallValue = getL1CallValue();\n require(address(this).balance >= requiredL1CallValue, \"Insufficient ETH balance\");\n }\n}\n" + }, + "contracts/chain-adapters/Arbitrum_SendTokensAdapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport { ArbitrumL1ERC20GatewayLike } from \"./Arbitrum_Adapter.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice This adapter is built for emergencies to send funds from the Hub to a Spoke in the event that a spoke pool\n * received a duplicate root bundle relay, due to some replay issue.\n */\n// solhint-disable-next-line contract-name-camelcase\ncontract Arbitrum_SendTokensAdapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n uint256 public immutable l2MaxSubmissionCost = 0.01e18;\n uint256 public immutable l2GasPrice = 5e9;\n uint32 public constant RELAY_TOKENS_L2_GAS_LIMIT = 300_000;\n\n ArbitrumL1ERC20GatewayLike public immutable l1ERC20GatewayRouter;\n address public immutable l2RefundL2Address;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1ERC20GatewayRouter ERC20 gateway router contract to send tokens to Arbitrum.\n * @param _l2RefundL2Address L2 address to receive gas refunds on after a message is relayed.\n */\n constructor(ArbitrumL1ERC20GatewayLike _l1ERC20GatewayRouter, address _l2RefundL2Address) {\n l1ERC20GatewayRouter = _l1ERC20GatewayRouter;\n l2RefundL2Address = _l2RefundL2Address;\n }\n\n /**\n * @notice Send tokens to SpokePool. Enables HubPool admin to call relaySpokePoolAdminFunction that will trigger\n * this function.\n * @dev This performs similar logic to relayTokens in the normal Arbitrum_Adapter by sending tokens\n * the Arbitrum_SpokePool out of the HubPool.\n * @param message The encoded address of the ERC20 to send to the rescue address.\n */\n function relayMessage(address target, bytes memory message) external payable override {\n (address l1Token, uint256 amount) = abi.decode(message, (address, uint256));\n\n uint256 requiredL1CallValue = _contractHasSufficientEthBalance();\n\n // Approve the gateway, not the router, to spend the hub pool's balance. The gateway, which is different\n // per L1 token, will temporarily escrow the tokens to be bridged and pull them from this contract.\n address erc20Gateway = l1ERC20GatewayRouter.getGateway(l1Token);\n IERC20(l1Token).safeIncreaseAllowance(erc20Gateway, amount);\n\n // `outboundTransfer` expects that the caller includes a bytes message as the last param that includes the\n // maxSubmissionCost to use when creating an L2 retryable ticket: https://github.com/OffchainLabs/arbitrum/blob/e98d14873dd77513b569771f47b5e05b72402c5e/packages/arb-bridge-peripherals/contracts/tokenbridge/ethereum/gateway/L1GatewayRouter.sol#L232\n bytes memory data = abi.encode(l2MaxSubmissionCost, \"\");\n\n l1ERC20GatewayRouter.outboundTransferCustomRefund{ value: requiredL1CallValue }(\n l1Token,\n l2RefundL2Address,\n target,\n amount,\n RELAY_TOKENS_L2_GAS_LIMIT,\n l2GasPrice,\n data\n );\n\n // Purposefully not emitting any events so as not to confuse off-chain monitors that track this event.\n // emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n\n /**\n * @notice Should never be called.\n */\n function relayTokens(\n address,\n address,\n uint256,\n address\n ) external payable override {\n revert(\"relayTokens disabled\");\n }\n\n /**\n * @notice Returns required amount of ETH to send a message via the Inbox.\n * @return amount of ETH that this contract needs to hold in order for relayMessage to succeed.\n */\n function getL1CallValue() public pure returns (uint256) {\n return l2MaxSubmissionCost + l2GasPrice * RELAY_TOKENS_L2_GAS_LIMIT;\n }\n\n function _contractHasSufficientEthBalance() internal view returns (uint256 requiredL1CallValue) {\n requiredL1CallValue = getL1CallValue();\n require(address(this).balance >= requiredL1CallValue, \"Insufficient ETH balance\");\n }\n}\n" + }, + "contracts/chain-adapters/Base_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\n// @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need\n// this contract's state variables to be `immutable` because of the delegateCall call.\nimport \"./CrossDomainEnabled.sol\";\nimport \"@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../libraries/CircleCCTPAdapter.sol\";\nimport \"../external/interfaces/CCTPInterfaces.sol\";\n\n/**\n * @notice Contract containing logic to send messages from L1 to Base. This is a modified version of the Optimism adapter\n * that excludes the custom bridging logic.\n * @custom:security-contact bugs@across.to\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Base_Adapter is CrossDomainEnabled, AdapterInterface, CircleCCTPAdapter {\n using SafeERC20 for IERC20;\n uint32 public constant L2_GAS_LIMIT = 200_000;\n\n WETH9Interface public immutable L1_WETH;\n\n IL1StandardBridge public immutable L1_STANDARD_BRIDGE;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1Weth WETH address on L1.\n * @param _crossDomainMessenger XDomainMessenger Base system contract.\n * @param _l1StandardBridge Standard bridge contract.\n * @param _l1Usdc USDC address on L1.\n * @param _cctpTokenMessenger TokenMessenger contract to bridge via CCTP.\n */\n constructor(\n WETH9Interface _l1Weth,\n address _crossDomainMessenger,\n IL1StandardBridge _l1StandardBridge,\n IERC20 _l1Usdc,\n ITokenMessenger _cctpTokenMessenger\n ) CrossDomainEnabled(_crossDomainMessenger) CircleCCTPAdapter(_l1Usdc, _cctpTokenMessenger, CircleDomainIds.Base) {\n L1_WETH = _l1Weth;\n L1_STANDARD_BRIDGE = _l1StandardBridge;\n }\n\n /**\n * @notice Send cross-chain message to target on Base.\n * @param target Contract on Base that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n sendCrossDomainMessage(target, L2_GAS_LIMIT, message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Base.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.\n if (l1Token == address(L1_WETH)) {\n L1_WETH.withdraw(amount);\n L1_STANDARD_BRIDGE.depositETHTo{ value: amount }(to, L2_GAS_LIMIT, \"\");\n }\n // Check if this token is USDC, which requires a custom bridge via CCTP.\n else if (_isCCTPEnabled() && l1Token == address(usdcToken)) {\n _transferUsdc(to, amount);\n } else {\n IL1StandardBridge _l1StandardBridge = L1_STANDARD_BRIDGE;\n\n IERC20(l1Token).safeIncreaseAllowance(address(_l1StandardBridge), amount);\n _l1StandardBridge.depositERC20To(l1Token, l2Token, to, amount, L2_GAS_LIMIT, \"\");\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/chain-adapters/Blast_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\n// @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need\n// this contract's state variables to be `immutable` because of the delegateCall call.\nimport \"./CrossDomainEnabled.sol\";\nimport { IL1StandardBridge } from \"@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../libraries/CircleCCTPAdapter.sol\";\nimport \"../external/interfaces/CCTPInterfaces.sol\";\n\ninterface IL1ERC20Bridge {\n /// @notice Sends ERC20 tokens to a receiver's address on the other chain. Note that if the\n /// ERC20 token on the other chain does not recognize the local token as the correct\n /// pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n /// this chain.\n /// @param _localToken Address of the ERC20 on this chain.\n /// @param _remoteToken Address of the corresponding token on the remote chain.\n /// @param _to Address of the receiver.\n /// @param _amount Amount of local tokens to deposit.\n /// @param _minGasLimit Minimum amount of gas that the bridge can be relayed with.\n /// @param _extraData Extra data to be sent with the transaction. Note that the recipient will\n /// not be triggered with this data, but it will be emitted and can be used\n /// to identify the transaction.\n function bridgeERC20To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external;\n}\n\n/**\n * @notice Contract containing logic to send messages from L1 to Blast. This is a modified version of the Optimism adapter\n * that excludes the custom bridging logic. It differs from the Base Adapter in that it uses a special\n * Blast contract to bridge WETH and DAI, which are yielding rebasing tokens on L2, WETH and USDB.\n * @custom:security-contact bugs@across.to\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Blast_Adapter is CrossDomainEnabled, AdapterInterface, CircleCCTPAdapter {\n using SafeERC20 for IERC20;\n uint32 public immutable L2_GAS_LIMIT; // 200,000 is a reasonable default.\n\n WETH9Interface public immutable L1_WETH;\n\n IL1StandardBridge public immutable L1_STANDARD_BRIDGE; // 0x697402166Fbf2F22E970df8a6486Ef171dbfc524\n\n // Bridge used to get yielding version of ERC20's on L2.\n IL1ERC20Bridge public immutable L1_BLAST_BRIDGE; // 0x3a05E5d33d7Ab3864D53aaEc93c8301C1Fa49115 on mainnet.\n address public immutable L1_DAI; // 0x6B175474E89094C44Da98b954EedeAC495271d0F on mainnet.\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1Weth WETH address on L1.\n * @param _crossDomainMessenger XDomainMessenger Blast system contract.\n * @param _l1StandardBridge Standard bridge contract.\n * @param _l1Usdc USDC address on L1.\n */\n constructor(\n WETH9Interface _l1Weth,\n address _crossDomainMessenger,\n IL1StandardBridge _l1StandardBridge,\n IERC20 _l1Usdc,\n IL1ERC20Bridge l1BlastBridge,\n address l1Dai,\n uint32 l2GasLimit\n )\n CrossDomainEnabled(_crossDomainMessenger)\n // Hardcode cctp messenger to 0x0 to disable CCTP bridging.\n CircleCCTPAdapter(_l1Usdc, ITokenMessenger(address(0)), CircleDomainIds.UNINTIALIZED)\n {\n L1_WETH = _l1Weth;\n L1_STANDARD_BRIDGE = _l1StandardBridge;\n L1_BLAST_BRIDGE = l1BlastBridge;\n L1_DAI = l1Dai;\n L2_GAS_LIMIT = l2GasLimit;\n }\n\n /**\n * @notice Send cross-chain message to target on Blast.\n * @param target Contract on Blast that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n sendCrossDomainMessage(target, L2_GAS_LIMIT, message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Blast.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // If token can be bridged into yield-ing version of ERC20 on L2 side, then use Blast Bridge, otherwise\n // use standard bridge.\n\n // If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.\n if (l1Token == address(L1_WETH)) {\n L1_WETH.withdraw(amount);\n // @dev: we can use the standard or the blast bridge to deposit ETH here:\n L1_STANDARD_BRIDGE.depositETHTo{ value: amount }(to, L2_GAS_LIMIT, \"\");\n }\n // Check if this token is DAI, then use the L1 Blast Bridge\n else if (l1Token == L1_DAI) {\n IERC20(l1Token).safeIncreaseAllowance(address(L1_BLAST_BRIDGE), amount);\n L1_BLAST_BRIDGE.bridgeERC20To(l1Token, l2Token, to, amount, L2_GAS_LIMIT, \"\");\n } else {\n IL1StandardBridge _l1StandardBridge = L1_STANDARD_BRIDGE;\n\n IERC20(l1Token).safeIncreaseAllowance(address(_l1StandardBridge), amount);\n _l1StandardBridge.depositERC20To(l1Token, l2Token, to, amount, L2_GAS_LIMIT, \"\");\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/chain-adapters/Blast_RescueAdapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport { USDYieldManager } from \"../Blast_DaiRetriever.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice This adapter is built to to retrieve Blast USDB from the USDBYieldManager contract on Ethereum that was\n * sent to the HubPool as the `recipient`. These funds should ideally be sent to the BlastRetriever address on\n * Ethereum. This contract can be used to retrieve these funds.\n */\n// solhint-disable-next-line contract-name-camelcase\ncontract Blast_RescueAdapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n address public immutable rescueAddress;\n\n USDYieldManager public immutable usdYieldManager;\n\n /**\n * @notice Constructs new Adapter.\n * @param _rescueAddress Rescue address to send funds to.\n */\n constructor(address _rescueAddress, USDYieldManager _usdYieldManager) {\n rescueAddress = _rescueAddress;\n usdYieldManager = _usdYieldManager;\n }\n\n /**\n * @notice Rescues the tokens from the calling contract.\n * @param message The encoded address of the ERC20 to send to the rescue addres.\n */\n function relayMessage(address, bytes memory message) external payable override {\n (uint256 requestId, uint256 hintId) = abi.decode(message, (uint256, uint256));\n require(usdYieldManager.claimWithdrawal(requestId, hintId), \"claim failed\");\n }\n\n /**\n * @notice Should never be called.\n */\n function relayTokens(\n address,\n address,\n uint256,\n address\n ) external payable override {\n revert(\"relayTokens disabled\");\n }\n}\n" + }, + "contracts/chain-adapters/Boba_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\n// @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need\n// this contract's state variables to be `immutable` because of the delegateCall call.\nimport \"./CrossDomainEnabled.sol\";\nimport \"@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice Contract containing logic to send messages from L1 to Boba. This is a modified version of the Optimism adapter\n * that excludes the custom bridging logic.\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Boba_Adapter is CrossDomainEnabled, AdapterInterface {\n using SafeERC20 for IERC20;\n uint32 public immutable L2_GAS_LIMIT = 2_000_000;\n\n WETH9Interface public immutable L1_WETH;\n\n IL1StandardBridge public immutable L1_STANDARD_BRIDGE;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1Weth WETH address on L1.\n * @param _crossDomainMessenger XDomainMessenger Boba system contract.\n * @param _l1StandardBridge Standard bridge contract.\n */\n constructor(\n WETH9Interface _l1Weth,\n address _crossDomainMessenger,\n IL1StandardBridge _l1StandardBridge\n ) CrossDomainEnabled(_crossDomainMessenger) {\n L1_WETH = _l1Weth;\n L1_STANDARD_BRIDGE = _l1StandardBridge;\n }\n\n /**\n * @notice Send cross-chain message to target on Boba.\n * @param target Contract on Boba that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n sendCrossDomainMessage(target, uint32(L2_GAS_LIMIT), message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Boba.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.\n if (l1Token == address(L1_WETH)) {\n L1_WETH.withdraw(amount);\n L1_STANDARD_BRIDGE.depositETHTo{ value: amount }(to, L2_GAS_LIMIT, \"\");\n } else {\n IL1StandardBridge _l1StandardBridge = L1_STANDARD_BRIDGE;\n\n IERC20(l1Token).safeIncreaseAllowance(address(_l1StandardBridge), amount);\n _l1StandardBridge.depositERC20To(l1Token, l2Token, to, amount, L2_GAS_LIMIT, \"\");\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/chain-adapters/CrossDomainEnabled.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/* Interface Imports */\nimport { ICrossDomainMessenger } from \"@eth-optimism/contracts/libraries/bridge/ICrossDomainMessenger.sol\";\n\n/**\n * @title CrossDomainEnabled\n * @custom:security-contact bugs@across.to\n * @dev Helper contract for contracts performing cross-domain communications between L1 and Optimism.\n * @dev This modifies the eth-optimism/CrossDomainEnabled contract only by changing state variables to be\n * immutable for use in contracts like the Optimism_Adapter which use delegateCall().\n */\ncontract CrossDomainEnabled {\n // Messenger contract used to send and recieve messages from the other domain.\n address public immutable MESSENGER;\n\n /**\n * @param _messenger Address of the CrossDomainMessenger on the current layer.\n */\n constructor(address _messenger) {\n MESSENGER = _messenger;\n }\n\n /**\n * Gets the messenger, usually from storage. This function is exposed in case a child contract\n * needs to override.\n * @return The address of the cross-domain messenger contract which should be used.\n */\n function getCrossDomainMessenger() internal virtual returns (ICrossDomainMessenger) {\n return ICrossDomainMessenger(MESSENGER);\n }\n\n /**\n * Sends a message to an account on another domain\n * @param _crossDomainTarget The intended recipient on the destination domain\n * @param _gasLimit The gasLimit for the receipt of the message on the target domain.\n * @param _message The data to send to the target (usually calldata to a function with\n * onlyFromCrossDomainAccount())\n */\n function sendCrossDomainMessage(\n address _crossDomainTarget,\n uint32 _gasLimit,\n bytes calldata _message\n ) internal {\n // slither-disable-next-line reentrancy-events, reentrancy-benign\n getCrossDomainMessenger().sendMessage(_crossDomainTarget, _message, _gasLimit);\n }\n}\n" + }, + "contracts/chain-adapters/Ethereum_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @custom:security-contact bugs@across.to\n * @notice Contract containing logic to send messages from L1 to Ethereum SpokePool.\n * @notice This contract should always be deployed on the same chain as the HubPool, as it acts as a pass-through\n * contract between HubPool and SpokePool on the same chain. Its named \"Ethereum_Adapter\" because a core assumption\n * is that the HubPool will be deployed on Ethereum, so this adapter will be used to communicate between HubPool\n * and the Ethereum_SpokePool.\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Ethereum_Adapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n /**\n * @notice Send message to target on Ethereum.\n * @notice This function, and contract overall, is not useful in practice except that the HubPool\n * expects to interact with the SpokePool via an Adapter, so when communicating to the Ethereum_SpokePool, it must\n * send messages via this pass-through contract.\n * @param target Contract that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n _executeCall(target, message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Send tokens to target.\n * @param l1Token L1 token to send.\n * @param l2Token Unused parameter in this contract.\n * @param amount Amount of L1 tokens to send.\n * @param to recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token, // l2Token is unused for ethereum since we are assuming that the HubPool is only deployed\n // on this network.\n uint256 amount,\n address to\n ) external payable override {\n IERC20(l1Token).safeTransfer(to, amount);\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n\n // Note: this snippet of code is copied from Governor.sol. Source: https://github.com/UMAprotocol/protocol/blob/5b37ea818a28479c01e458389a83c3e736306b17/packages/core/contracts/oracle/implementation/Governor.sol#L190-L207\n function _executeCall(address to, bytes memory data) private {\n // Note: this snippet of code is copied from Governor.sol and modified to not include any \"value\" field.\n\n bool success;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let inputData := add(data, 0x20)\n let inputDataSize := mload(data)\n // Hardcode value to be 0 for relayed governance calls in order to avoid addressing complexity of bridging\n // value cross-chain.\n success := call(gas(), to, 0, inputData, inputDataSize, 0, 0)\n }\n require(success, \"execute call failed\");\n }\n}\n" + }, + "contracts/chain-adapters/Ethereum_RescueAdapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice This adapter is built for emergencies to rescue funds from a Hub in the event of a misconfiguration or\n * security issue.\n */\n// solhint-disable-next-line contract-name-camelcase\ncontract Ethereum_RescueAdapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n address public immutable rescueAddress;\n\n /**\n * @notice Constructs new Adapter.\n * @param _rescueAddress Rescue address to send funds to.\n */\n constructor(address _rescueAddress) {\n rescueAddress = _rescueAddress;\n }\n\n /**\n * @notice Rescues the tokens from the calling contract.\n * @param message The encoded address of the ERC20 to send to the rescue addres.\n */\n function relayMessage(address, bytes memory message) external payable override {\n IERC20 tokenAddress = IERC20(abi.decode(message, (address)));\n\n // Transfer full balance of tokens to the rescue address.\n tokenAddress.safeTransfer(rescueAddress, tokenAddress.balanceOf(address(this)));\n }\n\n /**\n * @notice Should never be called.\n */\n function relayTokens(\n address,\n address,\n uint256,\n address\n ) external payable override {\n revert(\"relayTokens disabled\");\n }\n}\n" + }, + "contracts/chain-adapters/interfaces/AdapterInterface.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @notice Sends cross chain messages and tokens to contracts on a specific L2 network.\n * This interface is implemented by an adapter contract that is deployed on L1.\n */\n\ninterface AdapterInterface {\n event MessageRelayed(address target, bytes message);\n\n event TokensRelayed(address l1Token, address l2Token, uint256 amount, address to);\n\n /**\n * @notice Send message to `target` on L2.\n * @dev This method is marked payable because relaying the message might require a fee\n * to be paid by the sender to forward the message to L2. However, it will not send msg.value\n * to the target contract on L2.\n * @param target L2 address to send message to.\n * @param message Message to send to `target`.\n */\n function relayMessage(address target, bytes calldata message) external payable;\n\n /**\n * @notice Send `amount` of `l1Token` to `to` on L2. `l2Token` is the L2 address equivalent of `l1Token`.\n * @dev This method is marked payable because relaying the message might require a fee\n * to be paid by the sender to forward the message to L2. However, it will not send msg.value\n * to the target contract on L2.\n * @param l1Token L1 token to bridge.\n * @param l2Token L2 token to receive.\n * @param amount Amount of `l1Token` to bridge.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable;\n}\n" + }, + "contracts/chain-adapters/Linea_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\nimport { IMessageService, ITokenBridge, IUSDCBridge } from \"../external/interfaces/LineaInterfaces.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice Supports sending messages and tokens from L1 to Linea.\n * @custom:security-contact bugs@across.to\n */\n// solhint-disable-next-line contract-name-camelcase\ncontract Linea_Adapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n WETH9Interface public immutable L1_WETH;\n IMessageService public immutable L1_MESSAGE_SERVICE;\n ITokenBridge public immutable L1_TOKEN_BRIDGE;\n IUSDCBridge public immutable L1_USDC_BRIDGE;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1Weth WETH address on L1.\n * @param _l1MessageService Canonical message service contract on L1.\n * @param _l1TokenBridge Canonical token bridge contract on L1.\n * @param _l1UsdcBridge L1 USDC Bridge to ConsenSys's L2 Linea.\n */\n constructor(\n WETH9Interface _l1Weth,\n IMessageService _l1MessageService,\n ITokenBridge _l1TokenBridge,\n IUSDCBridge _l1UsdcBridge\n ) {\n L1_WETH = _l1Weth;\n L1_MESSAGE_SERVICE = _l1MessageService;\n L1_TOKEN_BRIDGE = _l1TokenBridge;\n L1_USDC_BRIDGE = _l1UsdcBridge;\n }\n\n /**\n * @notice Send cross-chain message to target on Linea.\n * @param target Contract on Linea that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n // Linea currently does not support auto-claiming of cross-chain messages that have\n // non-empty calldata. As we need to manually claim these messages, we can set the\n // message fees to 0.\n L1_MESSAGE_SERVICE.sendMessage(target, 0, message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Linea.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // If the l1Token is WETH then unwrap it to ETH then send the ETH directly\n // via the Canoncial Message Service.\n if (l1Token == address(L1_WETH)) {\n L1_WETH.withdraw(amount);\n L1_MESSAGE_SERVICE.sendMessage{ value: amount }(to, 0, \"\");\n }\n // If the l1Token is USDC, then we need sent it via the USDC Bridge.\n else if (l1Token == L1_USDC_BRIDGE.usdc()) {\n IERC20(l1Token).safeIncreaseAllowance(address(L1_USDC_BRIDGE), amount);\n L1_USDC_BRIDGE.depositTo(amount, to);\n }\n // For other tokens, we can use the Canonical Token Bridge.\n else {\n IERC20(l1Token).safeIncreaseAllowance(address(L1_TOKEN_BRIDGE), amount);\n L1_TOKEN_BRIDGE.bridgeToken(l1Token, amount, to);\n }\n\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/chain-adapters/Lisk_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\n// @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need\n// this contract's state variables to be `immutable` because of the delegateCall call.\nimport \"./CrossDomainEnabled.sol\";\nimport \"@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../libraries/CircleCCTPAdapter.sol\";\nimport \"../external/interfaces/CCTPInterfaces.sol\";\n\n/**\n * @notice Contract containing logic to send messages from L1 to Lisk. This is a clone of the Base/Mode adapter\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n * @custom:security-contact bugs@across.to\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Lisk_Adapter is CrossDomainEnabled, AdapterInterface, CircleCCTPAdapter {\n using SafeERC20 for IERC20;\n uint32 public constant L2_GAS_LIMIT = 200_000;\n\n WETH9Interface public immutable L1_WETH;\n\n IL1StandardBridge public immutable L1_STANDARD_BRIDGE;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1Weth WETH address on L1.\n * @param _crossDomainMessenger XDomainMessenger Lisk system contract.\n * @param _l1StandardBridge Standard bridge contract.\n * @param _l1Usdc USDC address on L1.\n */\n constructor(\n WETH9Interface _l1Weth,\n address _crossDomainMessenger,\n IL1StandardBridge _l1StandardBridge,\n IERC20 _l1Usdc\n )\n CrossDomainEnabled(_crossDomainMessenger)\n CircleCCTPAdapter(\n _l1Usdc,\n // Hardcode cctp messenger to 0x0 to disable CCTP bridging.\n ITokenMessenger(address(0)),\n CircleDomainIds.UNINTIALIZED\n )\n {\n L1_WETH = _l1Weth;\n L1_STANDARD_BRIDGE = _l1StandardBridge;\n }\n\n /**\n * @notice Send cross-chain message to target on Lisk.\n * @param target Contract on Lisk that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n sendCrossDomainMessage(target, L2_GAS_LIMIT, message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Lisk.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.\n if (l1Token == address(L1_WETH)) {\n L1_WETH.withdraw(amount);\n L1_STANDARD_BRIDGE.depositETHTo{ value: amount }(to, L2_GAS_LIMIT, \"\");\n }\n // Check if this token is USDC, which requires a custom bridge via CCTP.\n else if (_isCCTPEnabled() && l1Token == address(usdcToken)) {\n _transferUsdc(to, amount);\n } else {\n IL1StandardBridge _l1StandardBridge = L1_STANDARD_BRIDGE;\n\n IERC20(l1Token).safeIncreaseAllowance(address(_l1StandardBridge), amount);\n _l1StandardBridge.depositERC20To(l1Token, l2Token, to, amount, L2_GAS_LIMIT, \"\");\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/chain-adapters/Mock_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @notice Contract used for testing communication between HubPool and Adapter.\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Mock_Adapter is AdapterInterface {\n event RelayMessageCalled(address target, bytes message, address caller);\n\n event RelayTokensCalled(address l1Token, address l2Token, uint256 amount, address to, address caller);\n\n Mock_Bridge public immutable bridge;\n\n constructor() {\n bridge = new Mock_Bridge();\n }\n\n function relayMessage(address target, bytes calldata message) external payable override {\n bridge.bridgeMessage(target, message);\n emit RelayMessageCalled(target, message, msg.sender);\n }\n\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n IERC20(l1Token).approve(address(bridge), amount);\n bridge.bridgeTokens(l1Token, amount);\n emit RelayTokensCalled(l1Token, l2Token, amount, to, msg.sender);\n }\n}\n\n// This contract is intended to \"act like\" a simple version of an L2 bridge.\n// It's primarily meant to better reflect how a true L2 bridge interaction might work to give better gas estimates.\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Mock_Bridge {\n event BridgedTokens(address token, uint256 amount);\n event BridgedMessage(address target, bytes message);\n\n mapping(address => uint256) public deposits;\n\n function bridgeTokens(address token, uint256 amount) public {\n IERC20(token).transferFrom(msg.sender, address(this), amount);\n deposits[token] += amount;\n emit BridgedTokens(token, amount);\n }\n\n function bridgeMessage(address target, bytes calldata message) public {\n emit BridgedMessage(target, message);\n }\n}\n" + }, + "contracts/chain-adapters/Mode_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\n// @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need\n// this contract's state variables to be `immutable` because of the delegateCall call.\nimport \"./CrossDomainEnabled.sol\";\nimport \"@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../libraries/CircleCCTPAdapter.sol\";\nimport \"../external/interfaces/CCTPInterfaces.sol\";\n\n/**\n * @notice Contract containing logic to send messages from L1 to Mode. This is a clone of the Base adapter\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n * @custom:security-contact bugs@across.to\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Mode_Adapter is CrossDomainEnabled, AdapterInterface, CircleCCTPAdapter {\n using SafeERC20 for IERC20;\n uint32 public constant L2_GAS_LIMIT = 200_000;\n\n WETH9Interface public immutable L1_WETH;\n\n IL1StandardBridge public immutable L1_STANDARD_BRIDGE;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1Weth WETH address on L1.\n * @param _crossDomainMessenger XDomainMessenger Mode system contract.\n * @param _l1StandardBridge Standard bridge contract.\n * @param _l1Usdc USDC address on L1.\n */\n constructor(\n WETH9Interface _l1Weth,\n address _crossDomainMessenger,\n IL1StandardBridge _l1StandardBridge,\n IERC20 _l1Usdc\n )\n CrossDomainEnabled(_crossDomainMessenger)\n CircleCCTPAdapter(\n _l1Usdc,\n // Hardcode cctp messenger to 0x0 to disable CCTP bridging.\n ITokenMessenger(address(0)),\n CircleDomainIds.UNINTIALIZED\n )\n {\n L1_WETH = _l1Weth;\n L1_STANDARD_BRIDGE = _l1StandardBridge;\n }\n\n /**\n * @notice Send cross-chain message to target on Mode.\n * @param target Contract on Mode that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n sendCrossDomainMessage(target, L2_GAS_LIMIT, message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Mode.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.\n if (l1Token == address(L1_WETH)) {\n L1_WETH.withdraw(amount);\n L1_STANDARD_BRIDGE.depositETHTo{ value: amount }(to, L2_GAS_LIMIT, \"\");\n }\n // Check if this token is USDC, which requires a custom bridge via CCTP.\n else if (_isCCTPEnabled() && l1Token == address(usdcToken)) {\n _transferUsdc(to, amount);\n } else {\n IL1StandardBridge _l1StandardBridge = L1_STANDARD_BRIDGE;\n\n IERC20(l1Token).safeIncreaseAllowance(address(_l1StandardBridge), amount);\n _l1StandardBridge.depositERC20To(l1Token, l2Token, to, amount, L2_GAS_LIMIT, \"\");\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/chain-adapters/Optimism_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\nimport \"../libraries/CircleCCTPAdapter.sol\";\nimport \"../external/interfaces/CCTPInterfaces.sol\";\n\n// @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need\n// this contract's state variables to be `immutable` because of the delegateCall call.\nimport \"./CrossDomainEnabled.sol\";\nimport \"@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice Interface for Synthetix custom bridge to Optimism.\n */\ninterface SynthetixBridgeToOptimism is IL1StandardBridge {\n /**\n * @notice Send tokens to Optimism.\n * @param to Address to send tokens to on L2.\n * @param amount Amount of tokens to send.\n */\n function depositTo(address to, uint256 amount) external;\n}\n\n/**\n * @notice Contract containing logic to send messages from L1 to Optimism.\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore it's only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n * @custom:security-contact bugs@across.to\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Optimism_Adapter is CrossDomainEnabled, AdapterInterface, CircleCCTPAdapter {\n using SafeERC20 for IERC20;\n uint32 public constant L2_GAS_LIMIT = 200_000;\n\n WETH9Interface public immutable L1_WETH;\n\n IL1StandardBridge public immutable L1_STANDARD_BRIDGE;\n\n // Optimism has the ability to support \"custom\" bridges. These bridges are not supported by the canonical bridge\n // and so we need to store the address of the custom token and the associated bridge. In the event we want to\n // support a new token that is not supported by Optimism, we can add a new custom bridge for it and re-deploy the\n // adapter. A full list of custom optimism tokens and their associated bridges can be found here:\n // https://github.com/ethereum-optimism/ethereum-optimism.github.io/blob/master/optimism.tokenlist.json\n address public constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n address public constant DAI_OPTIMISM_BRIDGE = 0x10E6593CDda8c58a1d0f14C5164B376352a55f2F;\n address public constant SNX = 0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F;\n address public constant SNX_OPTIMISM_BRIDGE = 0x39Ea01a0298C315d149a490E34B59Dbf2EC7e48F;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1Weth WETH address on L1.\n * @param _crossDomainMessenger XDomainMessenger Optimism system contract.\n * @param _l1StandardBridge Standard bridge contract.\n * @param _l1Usdc USDC address on L1.\n * @param _cctpTokenMessenger TokenMessenger contract to bridge via CCTP.\n */\n constructor(\n WETH9Interface _l1Weth,\n address _crossDomainMessenger,\n IL1StandardBridge _l1StandardBridge,\n IERC20 _l1Usdc,\n ITokenMessenger _cctpTokenMessenger\n )\n CrossDomainEnabled(_crossDomainMessenger)\n CircleCCTPAdapter(_l1Usdc, _cctpTokenMessenger, CircleDomainIds.Optimism)\n {\n L1_WETH = _l1Weth;\n L1_STANDARD_BRIDGE = _l1StandardBridge;\n }\n\n /**\n * @notice Send cross-chain message to target on Optimism.\n * @param target Contract on Optimism that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n sendCrossDomainMessage(target, L2_GAS_LIMIT, message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Optimism.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.\n if (l1Token == address(L1_WETH)) {\n L1_WETH.withdraw(amount);\n L1_STANDARD_BRIDGE.depositETHTo{ value: amount }(to, L2_GAS_LIMIT, \"\");\n }\n // If the l1Token is USDC, then we send it to the CCTP bridge\n else if (_isCCTPEnabled() && l1Token == address(usdcToken)) {\n _transferUsdc(to, amount);\n } else {\n address bridgeToUse = address(L1_STANDARD_BRIDGE);\n\n // Check if the L1 token requires a custom bridge. If so, use that bridge over the standard bridge.\n if (l1Token == DAI) bridgeToUse = DAI_OPTIMISM_BRIDGE; // 1. DAI\n if (l1Token == SNX) bridgeToUse = SNX_OPTIMISM_BRIDGE; // 2. SNX\n\n IERC20(l1Token).safeIncreaseAllowance(bridgeToUse, amount);\n if (l1Token == SNX) SynthetixBridgeToOptimism(bridgeToUse).depositTo(to, amount);\n else IL1StandardBridge(bridgeToUse).depositERC20To(l1Token, l2Token, to, amount, L2_GAS_LIMIT, \"\");\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/chain-adapters/Polygon_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../libraries/CircleCCTPAdapter.sol\";\nimport \"../external/interfaces/CCTPInterfaces.sol\";\n\n/**\n * @notice Send tokens to Polygon.\n */\ninterface IRootChainManager {\n /**\n * @notice Send msg.value of ETH to Polygon\n * @param user Recipient of ETH on Polygon.\n */\n function depositEtherFor(address user) external payable;\n\n /**\n * @notice Send ERC20 tokens to Polygon.\n * @param user Recipient of L2 equivalent tokens on Polygon.\n * @param rootToken L1 Address of token to send.\n * @param depositData Data to pass to L2 including amount of tokens to send. Should be abi.encode(amount).\n */\n function depositFor(\n address user,\n address rootToken,\n bytes calldata depositData\n ) external;\n}\n\n/**\n * @notice Send arbitrary messages to Polygon.\n */\ninterface IFxStateSender {\n /**\n * @notice Send arbitrary message to Polygon.\n * @param _receiver Address on Polygon to receive message.\n * @param _data Message to send to `_receiver` on Polygon.\n */\n function sendMessageToChild(address _receiver, bytes calldata _data) external;\n}\n\n/**\n * @notice Similar to RootChainManager, but for Matic (Plasma) bridge.\n */\ninterface DepositManager {\n /**\n * @notice Send tokens to Polygon. Only used to send MATIC in this Polygon_Adapter.\n * @param token L1 token to send. Should be MATIC.\n * @param user Recipient of L2 equivalent tokens on Polygon.\n * @param amount Amount of `token` to send.\n */\n function depositERC20ForUser(\n address token,\n address user,\n uint256 amount\n ) external;\n}\n\n/**\n * @notice Sends cross chain messages Polygon L2 network.\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n * @custom:security-contact bugs@across.to\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Polygon_Adapter is AdapterInterface, CircleCCTPAdapter {\n using SafeERC20 for IERC20;\n IRootChainManager public immutable ROOT_CHAIN_MANAGER;\n IFxStateSender public immutable FX_STATE_SENDER;\n DepositManager public immutable DEPOSIT_MANAGER;\n address public immutable ERC20_PREDICATE;\n address public immutable L1_MATIC;\n WETH9Interface public immutable L1_WETH;\n\n /**\n * @notice Constructs new Adapter.\n * @param _rootChainManager RootChainManager Polygon system contract to deposit tokens over the PoS bridge.\n * @param _fxStateSender FxStateSender Polygon system contract to send arbitrary messages to L2.\n * @param _depositManager DepositManager Polygon system contract to deposit tokens over the Plasma bridge (Matic).\n * @param _erc20Predicate ERC20Predicate Polygon system contract to approve when depositing to the PoS bridge.\n * @param _l1Matic matic address on l1.\n * @param _l1Weth WETH address on L1.\n * @param _l1Usdc USDC address on L1.\n * @param _cctpTokenMessenger TokenMessenger contract to bridge via CCTP.\n */\n constructor(\n IRootChainManager _rootChainManager,\n IFxStateSender _fxStateSender,\n DepositManager _depositManager,\n address _erc20Predicate,\n address _l1Matic,\n WETH9Interface _l1Weth,\n IERC20 _l1Usdc,\n ITokenMessenger _cctpTokenMessenger\n ) CircleCCTPAdapter(_l1Usdc, _cctpTokenMessenger, CircleDomainIds.Polygon) {\n ROOT_CHAIN_MANAGER = _rootChainManager;\n FX_STATE_SENDER = _fxStateSender;\n DEPOSIT_MANAGER = _depositManager;\n ERC20_PREDICATE = _erc20Predicate;\n L1_MATIC = _l1Matic;\n L1_WETH = _l1Weth;\n }\n\n /**\n * @notice Send cross-chain message to target on Polygon.\n * @param target Contract on Polygon that will receive message.\n * @param message Data to send to target.\n */\n\n function relayMessage(address target, bytes calldata message) external payable override {\n FX_STATE_SENDER.sendMessageToChild(target, message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Polygon.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.\n if (l1Token == address(L1_WETH)) {\n L1_WETH.withdraw(amount);\n ROOT_CHAIN_MANAGER.depositEtherFor{ value: amount }(to);\n }\n // If the l1Token is USDC, then we send it to the CCTP bridge\n else if (_isCCTPEnabled() && l1Token == address(usdcToken)) {\n _transferUsdc(to, amount);\n } else if (l1Token == L1_MATIC) {\n IERC20(l1Token).safeIncreaseAllowance(address(DEPOSIT_MANAGER), amount);\n DEPOSIT_MANAGER.depositERC20ForUser(l1Token, to, amount);\n } else {\n IERC20(l1Token).safeIncreaseAllowance(ERC20_PREDICATE, amount);\n ROOT_CHAIN_MANAGER.depositFor(to, l1Token, abi.encode(amount));\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/chain-adapters/PolygonZkEVM_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\nimport \"../external/interfaces/IPolygonZkEVMBridge.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice Supports sending messages and tokens from L1 to PolygonZkEVM.\n * @custom:security-contact bugs@across.to\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract PolygonZkEVM_Adapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n WETH9Interface public immutable L1_WETH;\n // Address of Polygon zkEVM's Canonical Bridge on L1.\n IPolygonZkEVMBridge public immutable L1_POLYGON_ZKEVM_BRIDGE;\n\n // Polygon's internal network id for zkEVM.\n uint32 public constant POLYGON_ZKEVM_L2_NETWORK_ID = 1;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1Weth WETH address on L1.\n * @param _l1PolygonZkEVMBridge Canonical token bridge contract on L1.\n */\n constructor(WETH9Interface _l1Weth, IPolygonZkEVMBridge _l1PolygonZkEVMBridge) {\n L1_WETH = _l1Weth;\n L1_POLYGON_ZKEVM_BRIDGE = _l1PolygonZkEVMBridge;\n }\n\n /**\n * @notice Send cross-chain message to target on Polygon zkEVM.\n * @param target Contract on Polygon zkEVM that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n L1_POLYGON_ZKEVM_BRIDGE.bridgeMessage(POLYGON_ZKEVM_L2_NETWORK_ID, target, true, message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Polygon zkEVM.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // The mapped WETH address in the native Polygon zkEVM bridge contract does not match\n // the official WETH address. Therefore, if the l1Token is WETH then unwrap it to ETH\n // and send the ETH directly via as msg.value.\n if (l1Token == address(L1_WETH)) {\n L1_WETH.withdraw(amount);\n L1_POLYGON_ZKEVM_BRIDGE.bridgeAsset{ value: amount }(\n POLYGON_ZKEVM_L2_NETWORK_ID,\n to,\n amount,\n address(0),\n true,\n \"\"\n );\n } else {\n IERC20(l1Token).safeIncreaseAllowance(address(L1_POLYGON_ZKEVM_BRIDGE), amount);\n L1_POLYGON_ZKEVM_BRIDGE.bridgeAsset(POLYGON_ZKEVM_L2_NETWORK_ID, to, amount, l1Token, true, \"\");\n }\n\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/chain-adapters/Redstone_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\n// @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need\n// this contract's state variables to be `immutable` because of the delegateCall call.\nimport \"./CrossDomainEnabled.sol\";\nimport \"@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../libraries/CircleCCTPAdapter.sol\";\nimport \"../external/interfaces/CCTPInterfaces.sol\";\n\n/**\n * @notice Contract containing logic to send messages from L1 to Redstone. This is a clone of the Base/Mode adapter\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n * @custom:security-contact bugs@across.to\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Redstone_Adapter is CrossDomainEnabled, AdapterInterface, CircleCCTPAdapter {\n using SafeERC20 for IERC20;\n uint32 public constant L2_GAS_LIMIT = 200_000;\n\n WETH9Interface public immutable L1_WETH;\n\n IL1StandardBridge public immutable L1_STANDARD_BRIDGE;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1Weth WETH address on L1.\n * @param _crossDomainMessenger XDomainMessenger Redstone system contract.\n * @param _l1StandardBridge Standard bridge contract.\n * @param _l1Usdc USDC address on L1.\n */\n constructor(\n WETH9Interface _l1Weth,\n address _crossDomainMessenger,\n IL1StandardBridge _l1StandardBridge,\n IERC20 _l1Usdc\n )\n CrossDomainEnabled(_crossDomainMessenger)\n CircleCCTPAdapter(\n _l1Usdc,\n // Hardcode cctp messenger to 0x0 to disable CCTP bridging.\n ITokenMessenger(address(0)),\n CircleDomainIds.UNINTIALIZED\n )\n {\n L1_WETH = _l1Weth;\n L1_STANDARD_BRIDGE = _l1StandardBridge;\n }\n\n /**\n * @notice Send cross-chain message to target on Redstone.\n * @param target Contract on Redstone that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n sendCrossDomainMessage(target, L2_GAS_LIMIT, message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Redstone.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.\n if (l1Token == address(L1_WETH)) {\n L1_WETH.withdraw(amount);\n L1_STANDARD_BRIDGE.depositETHTo{ value: amount }(to, L2_GAS_LIMIT, \"\");\n }\n // Check if this token is USDC, which requires a custom bridge via CCTP.\n else if (_isCCTPEnabled() && l1Token == address(usdcToken)) {\n _transferUsdc(to, amount);\n } else {\n IL1StandardBridge _l1StandardBridge = L1_STANDARD_BRIDGE;\n\n IERC20(l1Token).safeIncreaseAllowance(address(_l1StandardBridge), amount);\n _l1StandardBridge.depositERC20To(l1Token, l2Token, to, amount, L2_GAS_LIMIT, \"\");\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/chain-adapters/Scroll_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@scroll-tech/contracts/L1/gateways/IL1GatewayRouter.sol\";\nimport \"@scroll-tech/contracts/L1/rollup/IL2GasPriceOracle.sol\";\nimport \"@scroll-tech/contracts/L1/IL1ScrollMessenger.sol\";\nimport \"./interfaces/AdapterInterface.sol\";\n\n/**\n * @title Scroll_Adapter\n * @notice Adapter contract deployed on L1 alongside the HubPool to facilitate token transfers\n * and arbitrary message relaying from L1 to L2.\n * @custom:security-contact bugs@across.to\n */\ncontract Scroll_Adapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n /**\n * @notice Used as the gas limit for relaying messages to L2.\n */\n uint32 public immutable L2_MESSAGE_RELAY_GAS_LIMIT;\n\n /**\n * @notice Use as the gas limit for relaying tokens to L2.\n */\n uint32 public immutable L2_TOKEN_RELAY_GAS_LIMIT;\n\n /**\n * @notice The address of the official l1GatewayRouter contract for Scroll for bridging tokens from L1 -> L2\n * @dev We can find these (main/test)net deployments here: https://docs.scroll.io/en/developers/scroll-contracts/#scroll-contracts\n */\n IL1GatewayRouter public immutable L1_GATEWAY_ROUTER;\n\n /**\n * @notice The address of the official messenger contract for Scroll from L1 -> L2\n * @dev We can find these (main/test)net deployments here: https://docs.scroll.io/en/developers/scroll-contracts/#scroll-contracts\n */\n IL1ScrollMessenger public immutable L1_SCROLL_MESSENGER;\n\n /**\n * @notice The address of the official gas price oracle contract for Scroll for estimating the relayer fee\n * @dev We can find these (main/test)net deployments here: https://docs.scroll.io/en/developers/scroll-contracts/#scroll-contracts\n */\n IL2GasPriceOracle public immutable L2_GAS_PRICE_ORACLE;\n\n /**************************************\n * PUBLIC FUNCTIONS *\n **************************************/\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1GatewayRouter Standard bridge contract.\n * @param _l1ScrollMessenger Scroll Messenger contract.\n * @param _l2GasPriceOracle Gas price oracle contract.\n * @param _l2MessageRelayGasLimit Gas limit for relaying messages to L2.\n * @param _l2TokenRelayGasLimit Gas limit for relaying tokens to L2.\n */\n constructor(\n IL1GatewayRouter _l1GatewayRouter,\n IL1ScrollMessenger _l1ScrollMessenger,\n IL2GasPriceOracle _l2GasPriceOracle,\n uint32 _l2MessageRelayGasLimit,\n uint32 _l2TokenRelayGasLimit\n ) {\n L1_GATEWAY_ROUTER = _l1GatewayRouter;\n L1_SCROLL_MESSENGER = _l1ScrollMessenger;\n L2_GAS_PRICE_ORACLE = _l2GasPriceOracle;\n L2_MESSAGE_RELAY_GAS_LIMIT = _l2MessageRelayGasLimit;\n L2_TOKEN_RELAY_GAS_LIMIT = _l2TokenRelayGasLimit;\n }\n\n /**\n * @notice Send message to `target` on Scroll.\n * @dev This message is marked payable because relaying the message will require\n * a fee that needs to be propagated to the Scroll Bridge. It will not send msg.value\n * to the target contract on L2.\n * @param target L2 address to send message to.\n * @param message Message to send to `target`.\n */\n function relayMessage(address target, bytes calldata message) external payable {\n // We can specifically send a message with 0 value to the Scroll Bridge\n // and it will not forward any ETH to the target contract on L2. However,\n // we need to set the payable value to msg.value to ensure that the Scroll\n // Bridge has enough gas to forward the message to L2.\n L1_SCROLL_MESSENGER.sendMessage{ value: _generateRelayerFee(L2_MESSAGE_RELAY_GAS_LIMIT) }(\n target,\n 0,\n message,\n L2_MESSAGE_RELAY_GAS_LIMIT\n );\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Send `amount` of `l1Token` to `to` on Scroll. `l2Token` is the Scroll address equivalent of `l1Token`.\n * @dev This method is marked payable because relaying the message might require a fee\n * to be paid by the sender to forward the message to L2. However, it will not send msg.value\n * to the target contract on L2.\n * @param l1Token L1 token to bridge.\n * @param l2Token L2 token to receive.\n * @param amount Amount of `l1Token` to bridge.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable {\n IL1GatewayRouter _l1GatewayRouter = L1_GATEWAY_ROUTER;\n\n // Confirm that the l2Token that we're trying to send is the correct counterpart\n // address\n address _l2Token = _l1GatewayRouter.getL2ERC20Address(l1Token);\n require(_l2Token == l2Token, \"l2Token Mismatch\");\n\n IERC20(l1Token).safeIncreaseAllowance(address(_l1GatewayRouter), amount);\n\n // The scroll bridge handles arbitrary ERC20 tokens and is mindful of\n // the official WETH address on-chain. We don't need to do anything specific\n // to differentiate between WETH and a separate ERC20.\n // Note: This happens due to the L1GatewayRouter.getERC20Gateway() call\n // Note: dev docs: https://docs.scroll.io/en/developers/l1-and-l2-bridging/eth-and-erc20-token-bridge/\n _l1GatewayRouter.depositERC20{ value: _generateRelayerFee(L2_TOKEN_RELAY_GAS_LIMIT) }(\n l1Token,\n to,\n amount,\n L2_TOKEN_RELAY_GAS_LIMIT\n );\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n /**\n * @notice Generates the relayer fee for a message to be sent to L2.\n * @dev Function will revert if the contract does not have enough ETH to pay the fee.\n * @param _l2GasLimit Gas limit for relaying message to L2.\n * @return l2Fee The relayer fee for the message.\n */\n function _generateRelayerFee(uint32 _l2GasLimit) internal view returns (uint256 l2Fee) {\n l2Fee = L2_GAS_PRICE_ORACLE.estimateCrossDomainMessageFee(_l2GasLimit);\n require(address(this).balance >= l2Fee, \"Insufficient ETH balance\");\n }\n}\n" + }, + "contracts/chain-adapters/Succinct_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/SuccinctInterfaces.sol\";\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Succinct_Adapter is AdapterInterface {\n ITelepathyBroadcaster public immutable succinctSourceAmb;\n uint16 public immutable destinationChainId;\n\n // Special Succinct event for additional tracking information.\n event SuccinctMessageRelayed(bytes32 messageRoot, uint16 destinationChainId, address target, bytes message);\n\n /**\n * @notice Constructs new Adapter.\n * @param _succinctSourceAmb address of the SourceAmb succinct contract for sending messages.\n * @param _destinationChainId chainId of the destination.\n */\n constructor(ITelepathyBroadcaster _succinctSourceAmb, uint16 _destinationChainId) {\n succinctSourceAmb = _succinctSourceAmb;\n destinationChainId = _destinationChainId;\n }\n\n /**\n * @notice Send cross-chain message to target on the destination.\n * @param target Contract on the destination that will receive the message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n bytes32 messageRoot = succinctSourceAmb.send(destinationChainId, target, message);\n\n // Note: this emits two events. MessageRelayed for the sake of compatibility with other adapters.\n // It emits SuccinctMessageRelayed to encode additional tracking information that is Succinct-specific.\n emit MessageRelayed(target, message);\n emit SuccinctMessageRelayed(messageRoot, destinationChainId, target, message);\n }\n\n /**\n * @notice No-op relay tokens method.\n */\n function relayTokens(\n address,\n address,\n uint256,\n address\n ) external payable override {\n // This method is intentionally left as a no-op.\n // If the adapter is intended to be able to relay tokens, this method should be overriden.\n }\n}\n" + }, + "contracts/chain-adapters/ZkSync_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\ninterface ZkSyncInterface {\n // _contractL2: L2 address of the contract to be called.\n // _l2Value: Amount of ETH to pass with the call to L2; used as msg.value for the transaction.\n // _calldata: Calldata of the transaction call; encoded the same way as in Ethereum.\n // _l2GasLimit: Gas limit of the L2 transaction call.\n // _l2GasPerPubdataByteLimit: A constant representing how much gas is required to publish a byte of data from\n // L1 to L2. https://era.zksync.io/docs/api/js/utils.html#gas\n // _factoryDeps: Bytecodes array containing the bytecode of the contract being deployed.\n // If the contract is a factory contract, the array contains the bytecodes of the contracts it can deploy.\n // _refundRecipient: Address that receives the rest of the fee after the transaction execution.\n // If refundRecipient == 0, L2 msg.sender is used. Note: If the _refundRecipient is a smart contract,\n // then during the L1 to L2 transaction its address is aliased.\n function requestL2Transaction(\n address _contractL2,\n uint256 _l2Value,\n bytes calldata _calldata,\n uint256 _l2GasLimit,\n uint256 _l2GasPerPubdataByteLimit,\n bytes[] calldata _factoryDeps,\n address _refundRecipient\n ) external payable returns (bytes32 canonicalTxHash);\n\n // @notice Estimates the cost in Ether of requesting execution of an L2 transaction from L1\n // @param _l1GasPrice Effective gas price on L1 (priority fee + base fee)\n // @param _l2GasLimit Gas limit for the L2 transaction\n // @param _l2GasPerPubdataByteLimit Gas limit for the L2 transaction per byte of pubdata\n // @return The estimated L2 gas for the transaction to be paid\n function l2TransactionBaseCost(\n uint256 _l1GasPrice,\n uint256 _l2GasLimit,\n uint256 _l2GasPerPubdataByteLimit\n ) external view returns (uint256);\n}\n\ninterface ZkBridgeLike {\n // @dev: Use ZkSyncInterface.requestL2Transaction to bridge WETH as ETH to L2.\n function deposit(\n address _l2Receiver,\n address _l1Token,\n uint256 _amount,\n uint256 _l2TxGasLimit,\n uint256 _l2TxGasPerPubdataByte,\n address _refundRecipient\n ) external payable returns (bytes32 txHash);\n}\n\n// Note: this contract just forwards the calls from the HubPool to ZkSync to avoid limits.\n// A modified ZKSync_Adapter should be deployed with this address swapped in for all zkSync addresses.\ncontract LimitBypassProxy is ZkSyncInterface, ZkBridgeLike {\n using SafeERC20 for IERC20;\n ZkSyncInterface public constant zkSync = ZkSyncInterface(0x32400084C286CF3E17e7B677ea9583e60a000324);\n ZkBridgeLike public constant zkErc20Bridge = ZkBridgeLike(0x57891966931Eb4Bb6FB81430E6cE0A03AAbDe063);\n\n function l2TransactionBaseCost(\n uint256 _l1GasPrice,\n uint256 _l2GasLimit,\n uint256 _l2GasPerPubdataByteLimit\n ) external view returns (uint256) {\n return zkSync.l2TransactionBaseCost(_l1GasPrice, _l2GasLimit, _l2GasPerPubdataByteLimit);\n }\n\n function requestL2Transaction(\n address _contractL2,\n uint256 _l2Value,\n bytes calldata _calldata,\n uint256 _l2GasLimit,\n uint256 _l2GasPerPubdataByteLimit,\n bytes[] calldata _factoryDeps,\n address _refundRecipient\n ) external payable returns (bytes32 canonicalTxHash) {\n return\n zkSync.requestL2Transaction{ value: msg.value }(\n _contractL2,\n _l2Value,\n _calldata,\n _l2GasLimit,\n _l2GasPerPubdataByteLimit,\n _factoryDeps,\n _refundRecipient\n );\n }\n\n function deposit(\n address _l2Receiver,\n address _l1Token,\n uint256 _amount,\n uint256 _l2TxGasLimit,\n uint256 _l2TxGasPerPubdataByte,\n address _refundRecipient\n ) external payable returns (bytes32 txHash) {\n IERC20(_l1Token).safeIncreaseAllowance(address(zkErc20Bridge), _amount);\n return\n zkErc20Bridge.deposit{ value: msg.value }(\n _l2Receiver,\n _l1Token,\n _amount,\n _l2TxGasLimit,\n _l2TxGasPerPubdataByte,\n _refundRecipient\n );\n }\n}\n\n/**\n * @notice Contract containing logic to send messages from L1 to ZkSync.\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n * @custom:security-contact bugs@across.to\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract ZkSync_Adapter is AdapterInterface {\n using SafeERC20 for IERC20;\n\n // We need to pay a base fee to the operator to include our L1 --> L2 transaction.\n // https://era.zksync.io/docs/dev/developer-guides/bridging/l1-l2.html#getting-the-base-cost\n\n // Generally, the following params are a bit hard to set and may change in the future once ZkSync\n // goes live. For now, we'll hardcode these and use aggressive values to ensure inclusion.\n\n // Limit on L2 gas to spend.\n uint256 public constant L2_GAS_LIMIT = 2_000_000;\n\n // How much gas is required to publish a byte of data from L1 to L2. 800 is the required value\n // as set here https://github.com/matter-labs/era-contracts/blob/6391c0d7bf6184d7f6718060e3991ba6f0efe4a7/ethereum/contracts/zksync/facets/Mailbox.sol#L226\n // Note, this value can change and will require an updated adapter.\n uint256 public constant L1_GAS_TO_L2_GAS_PER_PUB_DATA_LIMIT = 800;\n\n // This address receives any remaining fee after an L1 to L2 transaction completes.\n // If refund recipient = address(0) then L2 msg.sender is used, unless msg.sender is a contract then its address\n // gets aliased.\n address public immutable l2RefundAddress;\n\n // Hardcode the following ZkSync system contract addresses to save gas on construction. This adapter can be\n // redeployed in the event that the following addresses change.\n\n // Main contract used to send L1 --> L2 messages. Fetchable via `zks_getMainContract` method on JSON RPC.\n ZkSyncInterface public constant zkSyncMessageBridge = ZkSyncInterface(0x32400084C286CF3E17e7B677ea9583e60a000324);\n\n // Contract used to send ETH to L2. Note: this is the same address as the main contract, but separated to allow\n // only this contract to be swapped (leaving the main zkSync contract to be used for messaging).\n ZkSyncInterface public constant zkSyncEthBridge = ZkSyncInterface(0x32400084C286CF3E17e7B677ea9583e60a000324);\n\n // Bridges to send ERC20 and ETH to L2. Fetchable via `zks_getBridgeContracts` method on JSON RPC.\n ZkBridgeLike public constant zkErc20Bridge = ZkBridgeLike(0x57891966931Eb4Bb6FB81430E6cE0A03AAbDe063);\n\n // Set l1Weth at construction time to make testing easier.\n WETH9Interface public immutable l1Weth;\n\n event ZkSyncMessageRelayed(bytes32 canonicalTxHash);\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1Weth WETH address on L1.\n * @param _l2RefundAddress address that recieves excess gas refunds on L2.\n */\n constructor(WETH9Interface _l1Weth, address _l2RefundAddress) {\n l1Weth = _l1Weth;\n l2RefundAddress = _l2RefundAddress;\n }\n\n /**\n * @notice Send cross-chain message to target on ZkSync.\n * @notice This contract must hold at least getL1CallValue() amount of ETH to send a message, or the message\n * will revert.\n * @param target Contract on L2 that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes memory message) external payable override {\n uint256 txBaseCost = _contractHasSufficientEthBalance();\n\n // Returns the hash of the requested L2 transaction. This hash can be used to follow the transaction status.\n bytes32 canonicalTxHash = zkSyncMessageBridge.requestL2Transaction{ value: txBaseCost }(\n target,\n // We pass no ETH with the call, otherwise we'd need to add to the txBaseCost this value.\n 0,\n message,\n L2_GAS_LIMIT,\n L1_GAS_TO_L2_GAS_PER_PUB_DATA_LIMIT,\n new bytes[](0),\n l2RefundAddress\n );\n\n emit MessageRelayed(target, message);\n emit ZkSyncMessageRelayed(canonicalTxHash);\n }\n\n /**\n * @notice Bridge tokens to ZkSync.\n * @notice This contract must hold at least getL1CallValue() amount of ETH to send a message\n * or the message will revert.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token, // l2Token is unused.\n uint256 amount,\n address to\n ) external payable override {\n // This could revert if the relay amount is over the ZkSync deposit\n // limit: https://github.com/matter-labs/era-contracts/blob/main/ethereum/contracts/common/AllowList.sol#L150\n // We should make sure that the limit is either set very high or we need to do logic\n // that splits the amount to deposit into multiple chunks. We can't have\n // this function revert or the HubPool will not be able to proceed to the\n // next bundle. See more here:\n // https://github.com/matter-labs/era-contracts/blob/main/docs/Overview.md#deposit-limitation\n // https://github.com/matter-labs/era-contracts/blob/6391c0d7bf6184d7f6718060e3991ba6f0efe4a7/ethereum/contracts/zksync/facets/Mailbox.sol#L230\n uint256 txBaseCost = _contractHasSufficientEthBalance();\n\n // If the l1Token is WETH then unwrap it to ETH then send the ETH to the standard bridge along with the base\n // cost. I've tried sending WETH over the erc20Bridge directly but we receive the wrong WETH\n // on the L2 side. So, we need to unwrap the WETH into ETH and then send.\n bytes32 txHash;\n if (l1Token == address(l1Weth)) {\n l1Weth.withdraw(amount);\n // We cannot call the standard ERC20 bridge because it disallows ETH deposits.\n txHash = zkSyncEthBridge.requestL2Transaction{ value: txBaseCost + amount }(\n to,\n amount,\n \"\",\n L2_GAS_LIMIT,\n L1_GAS_TO_L2_GAS_PER_PUB_DATA_LIMIT,\n new bytes[](0),\n l2RefundAddress\n );\n } else {\n IERC20(l1Token).safeIncreaseAllowance(address(zkErc20Bridge), amount);\n txHash = zkErc20Bridge.deposit{ value: txBaseCost }(\n to,\n l1Token,\n amount,\n L2_GAS_LIMIT,\n L1_GAS_TO_L2_GAS_PER_PUB_DATA_LIMIT,\n l2RefundAddress\n );\n }\n\n emit TokensRelayed(l1Token, l2Token, amount, to);\n emit ZkSyncMessageRelayed(txHash);\n }\n\n /**\n * @notice Returns required amount of ETH to send a message.\n * @return amount of ETH that this contract needs to hold in order for relayMessage to succeed.\n */\n function getL1CallValue() public view returns (uint256) {\n // - tx.gasprice returns effective_gas_price. It's also used by Mailbox contract to estimate L2GasPrice\n // so using tx.gasprice should always pass this check that msg.value >= baseCost + _l2Value\n // https://github.com/matter-labs/era-contracts/blob/6391c0d7bf6184d7f6718060e3991ba6f0efe4a7/ethereum/contracts/zksync/facets/Mailbox.sol#L273\n // - priority_fee_per_gas = min(transaction.max_priority_fee_per_gas, transaction.max_fee_per_gas - block.base_fee_per_gas)\n // - effective_gas_price = priority_fee_per_gas + block.base_fee_per_gas\n return\n zkSyncMessageBridge.l2TransactionBaseCost(tx.gasprice, L2_GAS_LIMIT, L1_GAS_TO_L2_GAS_PER_PUB_DATA_LIMIT);\n }\n\n function _contractHasSufficientEthBalance() internal view returns (uint256 requiredL1CallValue) {\n requiredL1CallValue = getL1CallValue();\n require(address(this).balance >= requiredL1CallValue, \"Insufficient ETH balance\");\n }\n}\n" + }, + "contracts/chain-adapters/Zora_Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/AdapterInterface.sol\";\nimport \"../external/interfaces/WETH9Interface.sol\";\n\n// @dev Use local modified CrossDomainEnabled contract instead of one exported by eth-optimism because we need\n// this contract's state variables to be `immutable` because of the delegateCall call.\nimport \"./CrossDomainEnabled.sol\";\nimport \"@eth-optimism/contracts/L1/messaging/IL1StandardBridge.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../libraries/CircleCCTPAdapter.sol\";\nimport \"../external/interfaces/CCTPInterfaces.sol\";\n\n/**\n * @notice Contract containing logic to send messages from L1 to Zora. This is a clone of the Base/Mode adapter\n * @dev Public functions calling external contracts do not guard against reentrancy because they are expected to be\n * called via delegatecall, which will execute this contract's logic within the context of the originating contract.\n * For example, the HubPool will delegatecall these functions, therefore its only necessary that the HubPool's methods\n * that call this contract's logic guard against reentrancy.\n * @custom:security-contact bugs@across.to\n */\n\n// solhint-disable-next-line contract-name-camelcase\ncontract Zora_Adapter is CrossDomainEnabled, AdapterInterface, CircleCCTPAdapter {\n using SafeERC20 for IERC20;\n uint32 public constant L2_GAS_LIMIT = 200_000;\n\n WETH9Interface public immutable L1_WETH;\n\n IL1StandardBridge public immutable L1_STANDARD_BRIDGE;\n\n /**\n * @notice Constructs new Adapter.\n * @param _l1Weth WETH address on L1.\n * @param _crossDomainMessenger XDomainMessenger Zora system contract.\n * @param _l1StandardBridge Standard bridge contract.\n * @param _l1Usdc USDC address on L1.\n */\n constructor(\n WETH9Interface _l1Weth,\n address _crossDomainMessenger,\n IL1StandardBridge _l1StandardBridge,\n IERC20 _l1Usdc\n )\n CrossDomainEnabled(_crossDomainMessenger)\n CircleCCTPAdapter(\n _l1Usdc,\n // Hardcode cctp messenger to 0x0 to disable CCTP bridging.\n ITokenMessenger(address(0)),\n CircleDomainIds.UNINTIALIZED\n )\n {\n L1_WETH = _l1Weth;\n L1_STANDARD_BRIDGE = _l1StandardBridge;\n }\n\n /**\n * @notice Send cross-chain message to target on Zora.\n * @param target Contract on Zora that will receive message.\n * @param message Data to send to target.\n */\n function relayMessage(address target, bytes calldata message) external payable override {\n sendCrossDomainMessage(target, L2_GAS_LIMIT, message);\n emit MessageRelayed(target, message);\n }\n\n /**\n * @notice Bridge tokens to Zora.\n * @param l1Token L1 token to deposit.\n * @param l2Token L2 token to receive.\n * @param amount Amount of L1 tokens to deposit and L2 tokens to receive.\n * @param to Bridge recipient.\n */\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external payable override {\n // If the l1Token is weth then unwrap it to ETH then send the ETH to the standard bridge.\n if (l1Token == address(L1_WETH)) {\n L1_WETH.withdraw(amount);\n L1_STANDARD_BRIDGE.depositETHTo{ value: amount }(to, L2_GAS_LIMIT, \"\");\n }\n // Check if this token is USDC, which requires a custom bridge via CCTP.\n else if (_isCCTPEnabled() && l1Token == address(usdcToken)) {\n _transferUsdc(to, amount);\n } else {\n IL1StandardBridge _l1StandardBridge = L1_STANDARD_BRIDGE;\n\n IERC20(l1Token).safeIncreaseAllowance(address(_l1StandardBridge), amount);\n _l1StandardBridge.depositERC20To(l1Token, l2Token, to, amount, L2_GAS_LIMIT, \"\");\n }\n emit TokensRelayed(l1Token, l2Token, amount, to);\n }\n}\n" + }, + "contracts/erc1155/MintableERC1155.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\n\n/**\n * @title MintableERC1155\n * @notice Ownable contract enabling owner to airdrop many recipients the same token ID at once\n */\ncontract MintableERC1155 is ERC1155, Ownable {\n // Maps `tokenId` to metadata URI `tokenURI`\n mapping(uint256 => string) public _tokenURIs;\n\n event Airdrop(address caller, uint256 tokenId, address[] recipients, uint256 amount);\n\n // We are passing an empty string as the `baseURI` because we use `_tokenURIs` instead\n // to allow for IPFS URIs.\n // solhint-disable-next-line\n constructor() ERC1155(\"\") {}\n\n /**\n * @notice Creates `amount` new tokens for `recipients` of token type `tokenId`.\n * @dev Call might run out of gas if `recipients` arg too long. Might need to chunk up the list.\n * @param recipients List of airdrop recipients.\n * @param tokenId Token type to airdrop.\n * @param amount Amount of token types to airdrop.\n */\n function airdrop(\n uint256 tokenId,\n address[] memory recipients,\n uint256 amount\n ) public onlyOwner {\n for (uint256 i = 0; i < recipients.length; i++) {\n _mint(recipients[i], tokenId, amount, \"\");\n }\n emit Airdrop(_msgSender(), tokenId, recipients, amount);\n }\n\n /**\n * @notice Sets the URI for token of type `tokenId` to `tokenURI`.\n * @param tokenId Token type to set `tokenURI` for.\n * @param tokenURI URI of token metadata.\n */\n function setTokenURI(uint256 tokenId, string memory tokenURI) external onlyOwner {\n require(bytes(_tokenURIs[tokenId]).length == 0, \"uri already set\");\n\n _tokenURIs[tokenId] = tokenURI;\n emit URI(tokenURI, tokenId);\n }\n\n /**\n * @notice Returns metadata URI of token type `tokenId`.\n * @dev Instead of returning the same URI for *all* token types, we return the uri set by\n * `setTokenURI` to allow IPFS URIs for all token types.\n * @param tokenId Token type to retrieve metadata URI for.\n */\n function uri(uint256 tokenId) public view override returns (string memory) {\n return _tokenURIs[tokenId];\n }\n}\n" + }, + "contracts/erc7683/ERC7683.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\n/// @notice Tokens sent by the swapper as inputs to the order\nstruct Input {\n /// @dev The address of the ERC20 token on the origin chain\n address token;\n /// @dev The amount of the token to be sent\n uint256 amount;\n}\n\n/// @notice Tokens that must be received for a valid order fulfillment\nstruct Output {\n /// @dev The address of the ERC20 token on the destination chain\n /// @dev address(0) used as a sentinel for the native token\n address token;\n /// @dev The amount of the token to be sent\n uint256 amount;\n /// @dev The address to receive the output tokens\n address recipient;\n /// @dev The destination chain for this output\n uint32 chainId;\n}\n\n/// @title CrossChainOrder type\n/// @notice Standard order struct to be signed by swappers, disseminated to fillers, and submitted to settlement contracts\nstruct CrossChainOrder {\n /// @dev The contract address that the order is meant to be settled by.\n /// Fillers send this order to this contract address on the origin chain\n address settlementContract;\n /// @dev The address of the user who is initiating the swap,\n /// whose input tokens will be taken and escrowed\n address swapper;\n /// @dev Nonce to be used as replay protection for the order\n uint256 nonce;\n /// @dev The chainId of the origin chain\n uint32 originChainId;\n /// @dev The timestamp by which the order must be initiated\n uint32 initiateDeadline;\n /// @dev The timestamp by which the order must be filled on the destination chain\n uint32 fillDeadline;\n /// @dev Arbitrary implementation-specific data\n /// Can be used to define tokens, amounts, destination chains, fees, settlement parameters,\n /// or any other order-type specific information\n bytes orderData;\n}\n\n/// @title ResolvedCrossChainOrder type\n/// @notice An implementation-generic representation of an order\n/// @dev Defines all requirements for filling an order by unbundling the implementation-specific orderData.\n/// @dev Intended to improve integration generalization by allowing fillers to compute the exact input and output information of any order\nstruct ResolvedCrossChainOrder {\n /// @dev The contract address that the order is meant to be settled by.\n address settlementContract;\n /// @dev The address of the user who is initiating the swap\n address swapper;\n /// @dev Nonce to be used as replay protection for the order\n uint256 nonce;\n /// @dev The chainId of the origin chain\n uint32 originChainId;\n /// @dev The timestamp by which the order must be initiated\n uint32 initiateDeadline;\n /// @dev The timestamp by which the order must be filled on the destination chain(s)\n uint32 fillDeadline;\n /// @dev The inputs to be taken from the swapper as part of order initiation\n Input[] swapperInputs;\n /// @dev The outputs to be given to the swapper as part of order fulfillment\n Output[] swapperOutputs;\n /// @dev The outputs to be given to the filler as part of order settlement\n Output[] fillerOutputs;\n}\n\n/// @title ISettlementContract\n/// @notice Standard interface for settlement contracts\ninterface ISettlementContract {\n /// @notice Initiates the settlement of a cross-chain order\n /// @dev To be called by the filler\n /// @param order The CrossChainOrder definition\n /// @param signature The swapper's signature over the order\n /// @param fillerData Any filler-defined data required by the settler\n function initiate(\n CrossChainOrder memory order,\n bytes memory signature,\n bytes memory fillerData\n ) external;\n\n /// @notice Resolves a specific CrossChainOrder into a generic ResolvedCrossChainOrder\n /// @dev Intended to improve standardized integration of various order types and settlement contracts\n /// @param order The CrossChainOrder definition\n /// @param fillerData Any filler-defined data required by the settler\n /// @return ResolvedCrossChainOrder hydrated order data including the inputs and outputs of the order\n function resolve(CrossChainOrder memory order, bytes memory fillerData)\n external\n view\n returns (ResolvedCrossChainOrder memory);\n}\n" + }, + "contracts/erc7683/ERC7683Across.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"../external/interfaces/IPermit2.sol\";\nimport { CrossChainOrder } from \"./ERC7683.sol\";\n\n// Data unique to every CrossChainOrder settled on Across\nstruct AcrossOrderData {\n address inputToken;\n uint256 inputAmount;\n address outputToken;\n uint256 outputAmount;\n uint32 destinationChainId;\n address recipient;\n uint32 exclusivityDeadlineOffset;\n bytes message;\n}\n\nstruct AcrossFillerData {\n address exclusiveRelayer;\n}\n\n/**\n * @notice ERC7683Permit2Lib knows how to process a particular type of external Permit2Order so that it can be used in Across.\n * @dev This library is responsible for definining the ERC712 type strings/hashes and performing hashes on the types.\n * @custom:security-contact bugs@across.to\n */\nlibrary ERC7683Permit2Lib {\n bytes private constant ACROSS_ORDER_DATA_TYPE =\n abi.encodePacked(\n \"AcrossOrderData(\",\n \"address inputToken,\",\n \"uint256 inputAmount,\",\n \"address outputToken,\",\n \"uint256 outputAmount,\",\n \"uint32 destinationChainId,\",\n \"address recipient,\",\n \"uint32 exclusivityDeadlineOffset,\",\n \"bytes message)\"\n );\n\n bytes32 private constant ACROSS_ORDER_DATA_TYPE_HASH = keccak256(ACROSS_ORDER_DATA_TYPE);\n\n bytes internal constant CROSS_CHAIN_ORDER_TYPE =\n abi.encodePacked(\n \"CrossChainOrder(\",\n \"address settlementContract,\",\n \"address swapper,\",\n \"uint256 nonce,\",\n \"uint32 originChainId,\",\n \"uint32 initiateDeadline,\",\n \"uint32 fillDeadline,\",\n \"AcrossOrderData orderData)\"\n );\n\n bytes internal constant CROSS_CHAIN_ORDER_EIP712_TYPE =\n abi.encodePacked(CROSS_CHAIN_ORDER_TYPE, ACROSS_ORDER_DATA_TYPE);\n bytes32 internal constant CROSS_CHAIN_ORDER_TYPE_HASH = keccak256(CROSS_CHAIN_ORDER_EIP712_TYPE);\n\n string private constant TOKEN_PERMISSIONS_TYPE = \"TokenPermissions(address token,uint256 amount)\";\n string internal constant PERMIT2_ORDER_TYPE =\n string(\n abi.encodePacked(\n \"CrossChainOrder witness)\",\n ACROSS_ORDER_DATA_TYPE,\n CROSS_CHAIN_ORDER_TYPE,\n TOKEN_PERMISSIONS_TYPE\n )\n );\n\n // Hashes an order to get an order hash. Needed for permit2.\n function hashOrder(CrossChainOrder memory order, bytes32 orderDataHash) internal pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n CROSS_CHAIN_ORDER_TYPE_HASH,\n order.settlementContract,\n order.swapper,\n order.nonce,\n order.originChainId,\n order.initiateDeadline,\n order.fillDeadline,\n orderDataHash\n )\n );\n }\n\n function hashOrderData(AcrossOrderData memory orderData) internal pure returns (bytes32) {\n return\n keccak256(\n abi.encode(\n ACROSS_ORDER_DATA_TYPE_HASH,\n orderData.inputToken,\n orderData.inputAmount,\n orderData.outputToken,\n orderData.outputAmount,\n orderData.destinationChainId,\n orderData.recipient,\n orderData.exclusivityDeadlineOffset,\n keccak256(orderData.message)\n )\n );\n }\n}\n" + }, + "contracts/erc7683/ERC7683OrderDepositor.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"../external/interfaces/IPermit2.sol\";\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { Input, Output, CrossChainOrder, ResolvedCrossChainOrder, ISettlementContract } from \"./ERC7683.sol\";\nimport { AcrossOrderData, AcrossFillerData, ERC7683Permit2Lib } from \"./ERC7683Across.sol\";\n\n/**\n * @notice ERC7683OrderDepositor processes an external order type and translates it into an AcrossV3 deposit.\n * @dev This contract is abstract because it is intended to be usable by a contract that can accept the deposit\n * as well as one that sends the deposit to another contract.\n * @custom:security-contact bugs@across.to\n */\nabstract contract ERC7683OrderDepositor is ISettlementContract {\n error WrongSettlementContract();\n error WrongChainId();\n\n // Permit2 contract for this network.\n IPermit2 public immutable PERMIT2;\n\n // QUOTE_BEFORE_DEADLINE is subtracted from the deadline to get the quote timestamp.\n // This is a somewhat arbitrary conversion, but order creators need some way to precompute the quote timestamp.\n uint256 public immutable QUOTE_BEFORE_DEADLINE;\n\n /**\n * @notice Construct the Permit2Depositor.\n * @param _permit2 Permit2 contract\n * @param _quoteBeforeDeadline quoteBeforeDeadline is subtracted from the deadline to get the quote timestamp.\n */\n constructor(IPermit2 _permit2, uint256 _quoteBeforeDeadline) {\n PERMIT2 = _permit2;\n QUOTE_BEFORE_DEADLINE = _quoteBeforeDeadline;\n }\n\n /**\n * @notice Initiate the order.\n * @dev This will pull in the user's funds and make the order available to be filled.\n * @param order the ERC7683 compliant order.\n * @param signature signature for the EIP-712 compliant order type.\n * @param fillerData Across-specific fillerData.\n */\n function initiate(\n CrossChainOrder memory order,\n bytes memory signature,\n bytes memory fillerData\n ) external {\n // Ensure that order was intended to be settled by Across.\n if (order.settlementContract != address(this)) {\n revert WrongSettlementContract();\n }\n\n if (order.originChainId != block.chainid) {\n revert WrongChainId();\n }\n\n // Extract Across-specific params.\n (AcrossOrderData memory acrossOrderData, AcrossFillerData memory acrossFillerData) = decode(\n order.orderData,\n fillerData\n );\n\n // Verify Permit2 signature and pull user funds into this contract\n _processPermit2Order(order, acrossOrderData, signature);\n\n _callDeposit(\n order.swapper,\n acrossOrderData.recipient,\n acrossOrderData.inputToken,\n acrossOrderData.outputToken,\n acrossOrderData.inputAmount,\n acrossOrderData.outputAmount,\n acrossOrderData.destinationChainId,\n acrossFillerData.exclusiveRelayer,\n // Note: simplifying assumption to avoid quote timestamps that cause orders to expire before the deadline.\n SafeCast.toUint32(order.initiateDeadline - QUOTE_BEFORE_DEADLINE),\n order.fillDeadline,\n getCurrentTime() + acrossOrderData.exclusivityDeadlineOffset,\n acrossOrderData.message\n );\n }\n\n /**\n * @notice Constructs a ResolvedOrder from a CrossChainOrder and fillerData.\n * @param order the ERC7683 compliant order.\n * @param fillerData Across-specific fillerData.\n */\n function resolve(CrossChainOrder memory order, bytes memory fillerData)\n external\n view\n returns (ResolvedCrossChainOrder memory resolvedOrder)\n {\n if (order.settlementContract != address(this)) {\n revert WrongSettlementContract();\n }\n\n if (order.originChainId != block.chainid) {\n revert WrongChainId();\n }\n\n (AcrossOrderData memory acrossOrderData, AcrossFillerData memory acrossFillerData) = decode(\n order.orderData,\n fillerData\n );\n Input[] memory inputs = new Input[](1);\n inputs[0] = Input({ token: acrossOrderData.inputToken, amount: acrossOrderData.inputAmount });\n Output[] memory outputs = new Output[](1);\n outputs[0] = Output({\n token: acrossOrderData.outputToken,\n amount: acrossOrderData.outputAmount,\n recipient: acrossOrderData.recipient,\n chainId: acrossOrderData.destinationChainId\n });\n\n // We assume that filler takes repayment on the origin chain in which case the filler output\n // will always be equal to the input amount. If the filler requests repayment somewhere else then\n // the filler output will be equal to the input amount less a fee based on the chain they request\n // repayment on.\n Output[] memory fillerOutputs = new Output[](1);\n fillerOutputs[0] = Output({\n token: acrossOrderData.inputToken,\n amount: acrossOrderData.inputAmount,\n recipient: acrossFillerData.exclusiveRelayer,\n chainId: SafeCast.toUint32(block.chainid)\n });\n\n resolvedOrder = ResolvedCrossChainOrder({\n settlementContract: address(this),\n swapper: order.swapper,\n nonce: order.nonce,\n originChainId: order.originChainId,\n initiateDeadline: order.initiateDeadline,\n fillDeadline: order.fillDeadline,\n swapperInputs: inputs,\n swapperOutputs: outputs,\n fillerOutputs: fillerOutputs\n });\n }\n\n /**\n * @notice Decodes the Across specific orderData and fillerData into descriptive types.\n * @param orderData the orderData field of the ERC7683 compliant order.\n * @param fillerData Across-specific fillerData.\n * @return acrossOrderData decoded AcrossOrderData.\n * @return acrossFillerData decoded AcrossFillerData.\n */\n function decode(bytes memory orderData, bytes memory fillerData)\n public\n pure\n returns (AcrossOrderData memory, AcrossFillerData memory)\n {\n return (abi.decode(orderData, (AcrossOrderData)), abi.decode(fillerData, (AcrossFillerData)));\n }\n\n /**\n * @notice Gets the current time.\n * @return uint for the current timestamp.\n */\n function getCurrentTime() public view virtual returns (uint32) {\n return SafeCast.toUint32(block.timestamp); // solhint-disable-line not-rely-on-time\n }\n\n function _processPermit2Order(\n CrossChainOrder memory order,\n AcrossOrderData memory acrossOrderData,\n bytes memory signature\n ) internal {\n IPermit2.PermitTransferFrom memory permit = IPermit2.PermitTransferFrom({\n permitted: IPermit2.TokenPermissions({\n token: acrossOrderData.inputToken,\n amount: acrossOrderData.inputAmount\n }),\n nonce: order.nonce,\n deadline: order.initiateDeadline\n });\n\n IPermit2.SignatureTransferDetails memory signatureTransferDetails = IPermit2.SignatureTransferDetails({\n to: address(this),\n requestedAmount: acrossOrderData.inputAmount\n });\n\n // Pull user funds.\n PERMIT2.permitWitnessTransferFrom(\n permit,\n signatureTransferDetails,\n order.swapper,\n ERC7683Permit2Lib.hashOrder(order, ERC7683Permit2Lib.hashOrderData(acrossOrderData)), // witness data hash\n ERC7683Permit2Lib.PERMIT2_ORDER_TYPE, // witness data type string\n signature\n );\n }\n\n function _callDeposit(\n address depositor,\n address recipient,\n address inputToken,\n address outputToken,\n uint256 inputAmount,\n uint256 outputAmount,\n uint256 destinationChainId,\n address exclusiveRelayer,\n uint32 quoteTimestamp,\n uint32 fillDeadline,\n uint32 exclusivityDeadline,\n bytes memory message\n ) internal virtual;\n}\n" + }, + "contracts/erc7683/ERC7683OrderDepositorExternal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { ERC7683OrderDepositor } from \"./ERC7683OrderDepositor.sol\";\nimport \"../interfaces/V3SpokePoolInterface.sol\";\nimport \"../external/interfaces/IPermit2.sol\";\n\n/**\n * @notice ERC7683OrderDepositorExternal processes an external order type and translates it into an AcrossV3Deposit\n * that it sends to the SpokePool contract.\n * @custom:security-contact bugs@across.to\n */\ncontract ERC7683OrderDepositorExternal is ERC7683OrderDepositor {\n using SafeERC20 for IERC20;\n V3SpokePoolInterface public immutable SPOKE_POOL;\n\n constructor(\n V3SpokePoolInterface _spokePool,\n IPermit2 _permit2,\n uint256 _quoteBeforeDeadline\n ) ERC7683OrderDepositor(_permit2, _quoteBeforeDeadline) {\n SPOKE_POOL = _spokePool;\n }\n\n function _callDeposit(\n address depositor,\n address recipient,\n address inputToken,\n address outputToken,\n uint256 inputAmount,\n uint256 outputAmount,\n uint256 destinationChainId,\n address exclusiveRelayer,\n uint32 quoteTimestamp,\n uint32 fillDeadline,\n uint32 exclusivityDeadline,\n bytes memory message\n ) internal override {\n IERC20(inputToken).safeIncreaseAllowance(address(SPOKE_POOL), inputAmount);\n\n SPOKE_POOL.depositV3(\n depositor,\n recipient,\n inputToken,\n outputToken,\n inputAmount,\n outputAmount,\n destinationChainId,\n exclusiveRelayer,\n quoteTimestamp,\n fillDeadline,\n exclusivityDeadline,\n message\n );\n }\n}\n" + }, + "contracts/Ethereum_SpokePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./SpokePool.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\n\n/**\n * @notice Ethereum L1 specific SpokePool. Used on Ethereum L1 to facilitate L2->L1 transfers.\n * @custom:security-contact bugs@across.to\n */\ncontract Ethereum_SpokePool is SpokePool, OwnableUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeTokenAddress,\n uint32 _depositQuoteTimeBuffer,\n uint32 _fillDeadlineBuffer\n ) SpokePool(_wrappedNativeTokenAddress, _depositQuoteTimeBuffer, _fillDeadlineBuffer) {} // solhint-disable-line no-empty-blocks\n\n /**\n * @notice Construct the Ethereum SpokePool.\n * @dev crossDomainAdmin is unused on this contract.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n */\n function initialize(uint32 _initialDepositId, address _hubPool) public initializer {\n __Ownable_init();\n __SpokePool_init(_initialDepositId, _hubPool, _hubPool);\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n function _bridgeTokensToHubPool(uint256 amountToReturn, address l2TokenAddress) internal override {\n IERC20Upgradeable(l2TokenAddress).safeTransfer(hubPool, amountToReturn);\n }\n\n // The SpokePool deployed to the same network as the HubPool must be owned by the HubPool.\n // A core assumption of this contract system is that the HubPool is deployed on Ethereum.\n function _requireAdminSender() internal override onlyOwner {}\n}\n" + }, + "contracts/external/interfaces/CCTPInterfaces.sol": { + "content": "/**\n * Copyright (C) 2015, 2016, 2017 Dapphub\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see .\n */\n\n// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\n/**\n * Imported as-is from commit 139d8d0ce3b5531d3c7ec284f89d946dfb720016 of:\n * * https://github.com/walkerq/evm-cctp-contracts/blob/139d8d0ce3b5531d3c7ec284f89d946dfb720016/src/TokenMessenger.sol\n * Changes applied post-import:\n * * Removed a majority of code from this contract and converted the needed function signatures in this interface.\n */\ninterface ITokenMessenger {\n /**\n * @notice Deposits and burns tokens from sender to be minted on destination domain.\n * Emits a `DepositForBurn` event.\n * @dev reverts if:\n * - given burnToken is not supported\n * - given destinationDomain has no TokenMessenger registered\n * - transferFrom() reverts. For example, if sender's burnToken balance or approved allowance\n * to this contract is less than `amount`.\n * - burn() reverts. For example, if `amount` is 0.\n * - MessageTransmitter returns false or reverts.\n * @param amount amount of tokens to burn\n * @param destinationDomain destination domain\n * @param mintRecipient address of mint recipient on destination domain\n * @param burnToken address of contract to burn deposited tokens, on local domain\n * @return _nonce unique nonce reserved by message\n */\n function depositForBurn(\n uint256 amount,\n uint32 destinationDomain,\n bytes32 mintRecipient,\n address burnToken\n ) external returns (uint64 _nonce);\n\n /**\n * @notice Minter responsible for minting and burning tokens on the local domain\n * @dev A TokenMessenger stores a TokenMinter contract which extends the TokenController contract.\n * https://github.com/circlefin/evm-cctp-contracts/blob/817397db0a12963accc08ff86065491577bbc0e5/src/TokenMessenger.sol#L110\n * @return minter Token Minter contract.\n */\n function localMinter() external view returns (ITokenMinter minter);\n}\n\n/**\n * A TokenMessenger stores a TokenMinter contract which extends the TokenController contract. The TokenController\n * contract has a burnLimitsPerMessage public mapping which can be queried to find the per-message burn limit\n * for a given token:\n * https://github.com/circlefin/evm-cctp-contracts/blob/817397db0a12963accc08ff86065491577bbc0e5/src/TokenMinter.sol#L33\n * https://github.com/circlefin/evm-cctp-contracts/blob/817397db0a12963accc08ff86065491577bbc0e5/src/roles/TokenController.sol#L69C40-L69C60\n *\n */\ninterface ITokenMinter {\n /**\n * @notice Supported burnable tokens on the local domain\n * local token (address) => maximum burn amounts per message\n * @param token address of token contract\n * @return burnLimit maximum burn amount per message for token\n */\n function burnLimitsPerMessage(address token) external view returns (uint256);\n}\n" + }, + "contracts/external/interfaces/IPermit2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IPermit2 {\n struct TokenPermissions {\n address token;\n uint256 amount;\n }\n\n struct PermitTransferFrom {\n TokenPermissions permitted;\n uint256 nonce;\n uint256 deadline;\n }\n\n struct SignatureTransferDetails {\n address to;\n uint256 requestedAmount;\n }\n\n function permitWitnessTransferFrom(\n PermitTransferFrom memory permit,\n SignatureTransferDetails calldata transferDetails,\n address owner,\n bytes32 witness,\n string calldata witnessTypeString,\n bytes calldata signature\n ) external;\n\n function transferFrom(\n address from,\n address to,\n uint160 amount,\n address token\n ) external;\n}\n" + }, + "contracts/external/interfaces/IPolygonZkEVMBridge.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @notice Interface of Polygon zkEVM's Canonical Bridge\n * See https://github.com/0xPolygonHermez/zkevm-contracts/blob/53e95f3a236d8bea87c27cb8714a5d21496a3b20/contracts/interfaces/IPolygonZkEVMBridge.sol\n */\ninterface IPolygonZkEVMBridge {\n /**\n * @notice Deposit add a new leaf to the merkle tree\n * @param destinationNetwork Network destination\n * @param destinationAddress Address destination\n * @param amount Amount of tokens\n * @param token Token address, 0 address is reserved for ether\n * @param forceUpdateGlobalExitRoot Indicates if the new global exit root is updated or not\n * @param permitData Raw data of the call `permit` of the token\n */\n function bridgeAsset(\n uint32 destinationNetwork,\n address destinationAddress,\n uint256 amount,\n address token,\n bool forceUpdateGlobalExitRoot,\n bytes calldata permitData\n ) external payable;\n\n /**\n * @notice Bridge message and send ETH value\n * @param destinationNetwork Network destination\n * @param destinationAddress Address destination\n * @param forceUpdateGlobalExitRoot Indicates if the new global exit root is updated or not\n * @param metadata Message metadata\n */\n function bridgeMessage(\n uint32 destinationNetwork,\n address destinationAddress,\n bool forceUpdateGlobalExitRoot,\n bytes calldata metadata\n ) external payable;\n}\n" + }, + "contracts/external/interfaces/LineaInterfaces.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @notice Interface of Linea's Canonical Message Service\n * See https://github.com/Consensys/linea-contracts/blob/3cf85529fd4539eb06ba998030c37e47f98c528a/contracts/interfaces/IMessageService.sol\n */\ninterface IMessageService {\n /**\n * @notice Sends a message for transporting from the given chain.\n * @dev This function should be called with a msg.value = _value + _fee. The fee will be paid on the destination chain.\n * @param _to The destination address on the destination chain.\n * @param _fee The message service fee on the origin chain.\n * @param _calldata The calldata used by the destination message service to call the destination contract.\n */\n function sendMessage(\n address _to,\n uint256 _fee,\n bytes calldata _calldata\n ) external payable;\n\n /**\n * @notice Returns the original sender of the message on the origin layer.\n */\n function sender() external view returns (address);\n\n /**\n * @notice Minimum fee to use when sending a message. Currently, only exists on L2MessageService.\n * See https://github.com/Consensys/linea-contracts/blob/3cf85529fd4539eb06ba998030c37e47f98c528a/contracts/messageService/l2/L2MessageService.sol#L37\n */\n function minimumFeeInWei() external view returns (uint256);\n}\n\n/**\n * @notice Interface of Linea's Canonical Token Bridge\n * See https://github.com/Consensys/linea-contracts/blob/3cf85529fd4539eb06ba998030c37e47f98c528a/contracts/tokenBridge/interfaces/ITokenBridge.sol\n */\ninterface ITokenBridge {\n /**\n * @notice This function is the single entry point to bridge tokens to the\n * other chain, both for native and already bridged tokens. You can use it\n * to bridge any ERC20. If the token is bridged for the first time an ERC20\n * (BridgedToken.sol) will be automatically deployed on the target chain.\n * @dev User should first allow the bridge to transfer tokens on his behalf.\n * Alternatively, you can use `bridgeTokenWithPermit` to do so in a single\n * transaction. If you want the transfer to be automatically executed on the\n * destination chain. You should send enough ETH to pay the postman fees.\n * Note that Linea can reserve some tokens (which use a dedicated bridge).\n * In this case, the token cannot be bridged. Linea can only reserve tokens\n * that have not been bridged yet.\n * Linea can pause the bridge for security reason. In this case new bridge\n * transaction would revert.\n * @param _token The address of the token to be bridged.\n * @param _amount The amount of the token to be bridged.\n * @param _recipient The address that will receive the tokens on the other chain.\n */\n function bridgeToken(\n address _token,\n uint256 _amount,\n address _recipient\n ) external payable;\n}\n\ninterface IUSDCBridge {\n function usdc() external view returns (address);\n\n /**\n * @dev Sends the sender's USDC from L1 to the recipient on L2, locks the USDC sent\n * in this contract and sends a message to the message bridge\n * contract to mint the equivalent USDC on L2\n * @param amount The amount of USDC to send\n * @param to The recipient's address to receive the funds\n */\n function depositTo(uint256 amount, address to) external payable;\n}\n" + }, + "contracts/external/interfaces/SuccinctInterfaces.sol": { + "content": "pragma solidity ^0.8.0;\n\n// These interfaces are a subset of the Succinct interfaces here: https://github.com/succinctlabs/telepathy-contracts.\n\n// This interface should be implemented by any contract wanting to receive messages sent over the Succinct bridge.\ninterface ITelepathyHandler {\n function handleTelepathy(\n uint16 _sourceChainId,\n address _senderAddress,\n bytes memory _data\n ) external returns (bytes4);\n}\n\n// This interface represents the contract that we call into to send messages over the Succinct AMB.\ninterface ITelepathyBroadcaster {\n function send(\n uint16 _recipientChainId,\n address _recipientAddress,\n bytes calldata _data\n ) external returns (bytes32);\n}\n" + }, + "contracts/external/interfaces/WETH9Interface.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @notice Interface for the WETH9 contract.\n */\ninterface WETH9Interface {\n /**\n * @notice Burn Wrapped Ether and receive native Ether.\n * @param wad Amount of WETH to unwrap and send to caller.\n */\n function withdraw(uint256 wad) external;\n\n /**\n * @notice Lock native Ether and mint Wrapped Ether ERC20\n * @dev msg.value is amount of Wrapped Ether to mint/Ether to lock.\n */\n function deposit() external payable;\n\n /**\n * @notice Get balance of WETH held by `guy`.\n * @param guy Address to get balance of.\n * @return wad Amount of WETH held by `guy`.\n */\n function balanceOf(address guy) external view returns (uint256 wad);\n\n /**\n * @notice Transfer `wad` of WETH from caller to `guy`.\n * @param guy Address to send WETH to.\n * @param wad Amount of WETH to send.\n * @return ok True if transfer succeeded.\n */\n function transfer(address guy, uint256 wad) external returns (bool);\n}\n" + }, + "contracts/external/WETH9.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\n/**\n * Copyright (C) 2015, 2016, 2017 Dapphub\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program. If not, see .\n */\n\n/**\n * Imported as at commit 33d01d471437e1ab6861e4545ea4bb3895fd4d74 from:\n * UMAprotocol/protocol/packages/core/contracts/financial-templates/common/WETH9.sol\n * Changes applied post-import:\n * - Corrected SPDX-License-Identifier & reinstated GPLv3 license header.\n * - Permit transferFrom() to be overridden by marking it virtual.\n */\n\npragma solidity ^0.8.0;\n\ncontract WETH9 {\n string public name = \"Wrapped Ether\";\n string public symbol = \"WETH\";\n uint8 public decimals = 18;\n\n event Approval(address indexed src, address indexed guy, uint256 wad);\n event Transfer(address indexed src, address indexed dst, uint256 wad);\n event Deposit(address indexed dst, uint256 wad);\n event Withdrawal(address indexed src, uint256 wad);\n\n mapping(address => uint256) public balanceOf;\n mapping(address => mapping(address => uint256)) public allowance;\n\n receive() external payable {\n deposit();\n }\n\n fallback() external payable {\n deposit();\n }\n\n function deposit() public payable {\n balanceOf[msg.sender] += msg.value;\n emit Deposit(msg.sender, msg.value);\n }\n\n function withdraw(uint256 wad) public {\n require(balanceOf[msg.sender] >= wad);\n balanceOf[msg.sender] -= wad;\n payable(msg.sender).transfer(wad);\n emit Withdrawal(msg.sender, wad);\n }\n\n function totalSupply() public view returns (uint256) {\n return address(this).balance;\n }\n\n function approve(address guy, uint256 wad) public returns (bool) {\n allowance[msg.sender][guy] = wad;\n emit Approval(msg.sender, guy, wad);\n return true;\n }\n\n function transfer(address dst, uint256 wad) public returns (bool) {\n return transferFrom(msg.sender, dst, wad);\n }\n\n /**\n * @dev Local change: marked virtual to allow overriding.\n */\n function transferFrom(\n address src,\n address dst,\n uint256 wad\n ) public virtual returns (bool) {\n require(balanceOf[src] >= wad);\n\n if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) {\n require(allowance[src][msg.sender] >= wad);\n allowance[src][msg.sender] -= wad;\n }\n\n balanceOf[src] -= wad;\n balanceOf[dst] += wad;\n\n emit Transfer(src, dst, wad);\n\n return true;\n }\n}\n" + }, + "contracts/handlers/MulticallHandler.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"../interfaces/SpokePoolMessageHandler.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\n/**\n * @title Across Multicall contract that allows a user to specify a series of calls that should be made by the handler\n * via the message field in the deposit.\n * @dev This contract makes the calls blindly. The contract will send any remaining tokens The caller should ensure that the tokens recieved by the handler are completely consumed.\n */\ncontract MulticallHandler is AcrossMessageHandler, ReentrancyGuard {\n using SafeERC20 for IERC20;\n using Address for address payable;\n\n struct Call {\n address target;\n bytes callData;\n uint256 value;\n }\n\n struct Instructions {\n // Calls that will be attempted.\n Call[] calls;\n // Where the tokens go if any part of the call fails.\n // Leftover tokens are sent here as well if the action succeeds.\n address fallbackRecipient;\n }\n\n // Emitted when one of the calls fails. Note: all calls are reverted in this case.\n event CallsFailed(Call[] calls, address indexed fallbackRecipient);\n\n // Emitted when there are leftover tokens that are sent to the fallbackRecipient.\n event DrainedTokens(address indexed recipient, address indexed token, uint256 indexed amount);\n\n // Errors\n error CallReverted(uint256 index, Call[] calls);\n error NotSelf();\n error InvalidCall(uint256 index, Call[] calls);\n\n modifier onlySelf() {\n _requireSelf();\n _;\n }\n\n /**\n * @notice Main entrypoint for the handler called by the SpokePool contract.\n * @dev This will execute all calls encoded in the msg. The caller is responsible for making sure all tokens are\n * drained from this contract by the end of the series of calls. If not, they can be stolen.\n * A drainLeftoverTokens call can be included as a way to drain any remaining tokens from this contract.\n * @param message abi encoded array of Call structs, containing a target, callData, and value for each call that\n * the contract should make.\n */\n function handleV3AcrossMessage(\n address token,\n uint256,\n address,\n bytes memory message\n ) external nonReentrant {\n Instructions memory instructions = abi.decode(message, (Instructions));\n\n // If there is no fallback recipient, call and revert if the inner call fails.\n if (instructions.fallbackRecipient == address(0)) {\n this.attemptCalls(instructions.calls);\n return;\n }\n\n // Otherwise, try the call and send to the fallback recipient if any tokens are leftover.\n (bool success, ) = address(this).call(abi.encodeCall(this.attemptCalls, (instructions.calls)));\n if (!success) emit CallsFailed(instructions.calls, instructions.fallbackRecipient);\n\n // If there are leftover tokens, send them to the fallback recipient regardless of execution success.\n _drainRemainingTokens(token, payable(instructions.fallbackRecipient));\n }\n\n function attemptCalls(Call[] memory calls) external onlySelf {\n uint256 length = calls.length;\n for (uint256 i = 0; i < length; ++i) {\n Call memory call = calls[i];\n\n // If we are calling an EOA with calldata, assume target was incorrectly specified and revert.\n if (call.callData.length > 0 && call.target.code.length == 0) {\n revert InvalidCall(i, calls);\n }\n\n (bool success, ) = call.target.call{ value: call.value }(call.callData);\n if (!success) revert CallReverted(i, calls);\n }\n }\n\n function drainLeftoverTokens(address token, address payable destination) external onlySelf {\n _drainRemainingTokens(token, destination);\n }\n\n function _drainRemainingTokens(address token, address payable destination) internal {\n if (token != address(0)) {\n // ERC20 token.\n uint256 amount = IERC20(token).balanceOf(address(this));\n if (amount > 0) {\n IERC20(token).safeTransfer(destination, amount);\n emit DrainedTokens(destination, token, amount);\n }\n } else {\n // Send native token\n uint256 amount = address(this).balance;\n if (amount > 0) {\n destination.sendValue(amount);\n }\n }\n }\n\n function _requireSelf() internal view {\n // Must be called by this contract to ensure that this cannot be triggered without the explicit consent of the\n // depositor (for a valid relay).\n if (msg.sender != address(this)) revert NotSelf();\n }\n\n // Used if the caller is trying to unwrap the native token to this contract.\n receive() external payable {}\n}\n" + }, + "contracts/interfaces/HubPoolInterface.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @notice Concise list of functions in HubPool implementation.\n */\ninterface HubPoolInterface {\n // This leaf is meant to be decoded in the HubPool to rebalance tokens between HubPool and SpokePool.\n struct PoolRebalanceLeaf {\n // This is used to know which chain to send cross-chain transactions to (and which SpokePool to send to).\n uint256 chainId;\n // Total LP fee amount per token in this bundle, encompassing all associated bundled relays.\n uint256[] bundleLpFees;\n // Represents the amount to push to or pull from the SpokePool. If +, the pool pays the SpokePool. If negative\n // the SpokePool pays the HubPool. There can be arbitrarily complex rebalancing rules defined offchain. This\n // number is only nonzero when the rules indicate that a rebalancing action should occur. When a rebalance does\n // occur, runningBalances must be set to zero for this token and netSendAmounts should be set to the previous\n // runningBalances + relays - deposits in this bundle. If non-zero then it must be set on the SpokePool's\n // RelayerRefundLeaf amountToReturn as -1 * this value to show if funds are being sent from or to the SpokePool.\n int256[] netSendAmounts;\n // This is only here to be emitted in an event to track a running unpaid balance between the L2 pool and the L1\n // pool. A positive number indicates that the HubPool owes the SpokePool funds. A negative number indicates that\n // the SpokePool owes the HubPool funds. See the comment above for the dynamics of this and netSendAmounts.\n int256[] runningBalances;\n // Used by data worker to mark which leaves should relay roots to SpokePools, and to otherwise organize leaves.\n // For example, each leaf should contain all the rebalance information for a single chain, but in the case where\n // the list of l1Tokens is very large such that they all can't fit into a single leaf that can be executed under\n // the block gas limit, then the data worker can use this groupIndex to organize them. Any leaves with\n // a groupIndex equal to 0 will relay roots to the SpokePool, so the data worker should ensure that only one\n // leaf for a specific chainId should have a groupIndex equal to 0.\n uint256 groupIndex;\n // Used as the index in the bitmap to track whether this leaf has been executed or not.\n uint8 leafId;\n // The bundleLpFees, netSendAmounts, and runningBalances are required to be the same length. They are parallel\n // arrays for the given chainId and should be ordered by the l1Tokens field. All whitelisted tokens with nonzero\n // relays on this chain in this bundle in the order of whitelisting.\n address[] l1Tokens;\n }\n\n // A data worker can optimistically store several merkle roots on this contract by staking a bond and calling\n // proposeRootBundle. By staking a bond, the data worker is alleging that the merkle roots all contain valid leaves\n // that can be executed later to:\n // - Send funds from this contract to a SpokePool or vice versa\n // - Send funds from a SpokePool to Relayer as a refund for a relayed deposit\n // - Send funds from a SpokePool to a deposit recipient to fulfill a \"slow\" relay\n // Anyone can dispute this struct if the merkle roots contain invalid leaves before the\n // challengePeriodEndTimestamp. Once the expiration timestamp is passed, executeRootBundle to execute a leaf\n // from the poolRebalanceRoot on this contract and it will simultaneously publish the relayerRefundRoot and\n // slowRelayRoot to a SpokePool. The latter two roots, once published to the SpokePool, contain\n // leaves that can be executed on the SpokePool to pay relayers or recipients.\n struct RootBundle {\n // Contains leaves instructing this contract to send funds to SpokePools.\n bytes32 poolRebalanceRoot;\n // Relayer refund merkle root to be published to a SpokePool.\n bytes32 relayerRefundRoot;\n // Slow relay merkle root to be published to a SpokePool.\n bytes32 slowRelayRoot;\n // This is a 1D bitmap, with max size of 256 elements, limiting us to 256 chainsIds.\n uint256 claimedBitMap;\n // Proposer of this root bundle.\n address proposer;\n // Number of pool rebalance leaves to execute in the poolRebalanceRoot. After this number\n // of leaves are executed, a new root bundle can be proposed\n uint8 unclaimedPoolRebalanceLeafCount;\n // When root bundle challenge period passes and this root bundle becomes executable.\n uint32 challengePeriodEndTimestamp;\n }\n\n // Each whitelisted L1 token has an associated pooledToken struct that contains all information used to track the\n // cumulative LP positions and if this token is enabled for deposits.\n struct PooledToken {\n // LP token given to LPs of a specific L1 token.\n address lpToken;\n // True if accepting new LP's.\n bool isEnabled;\n // Timestamp of last LP fee update.\n uint32 lastLpFeeUpdate;\n // Number of LP funds sent via pool rebalances to SpokePools and are expected to be sent\n // back later.\n int256 utilizedReserves;\n // Number of LP funds held in contract less utilized reserves.\n uint256 liquidReserves;\n // Number of LP funds reserved to pay out to LPs as fees.\n uint256 undistributedLpFees;\n }\n\n // Helper contracts to facilitate cross chain actions between HubPool and SpokePool for a specific network.\n struct CrossChainContract {\n address adapter;\n address spokePool;\n }\n\n function setPaused(bool pause) external;\n\n function emergencyDeleteProposal() external;\n\n function relaySpokePoolAdminFunction(uint256 chainId, bytes memory functionData) external;\n\n function setProtocolFeeCapture(address newProtocolFeeCaptureAddress, uint256 newProtocolFeeCapturePct) external;\n\n function setBond(IERC20 newBondToken, uint256 newBondAmount) external;\n\n function setLiveness(uint32 newLiveness) external;\n\n function setIdentifier(bytes32 newIdentifier) external;\n\n function setCrossChainContracts(\n uint256 l2ChainId,\n address adapter,\n address spokePool\n ) external;\n\n function enableL1TokenForLiquidityProvision(address l1Token) external;\n\n function disableL1TokenForLiquidityProvision(address l1Token) external;\n\n function addLiquidity(address l1Token, uint256 l1TokenAmount) external payable;\n\n function removeLiquidity(\n address l1Token,\n uint256 lpTokenAmount,\n bool sendEth\n ) external;\n\n function exchangeRateCurrent(address l1Token) external returns (uint256);\n\n function liquidityUtilizationCurrent(address l1Token) external returns (uint256);\n\n function liquidityUtilizationPostRelay(address l1Token, uint256 relayedAmount) external returns (uint256);\n\n function sync(address l1Token) external;\n\n function proposeRootBundle(\n uint256[] memory bundleEvaluationBlockNumbers,\n uint8 poolRebalanceLeafCount,\n bytes32 poolRebalanceRoot,\n bytes32 relayerRefundRoot,\n bytes32 slowRelayRoot\n ) external;\n\n function executeRootBundle(\n uint256 chainId,\n uint256 groupIndex,\n uint256[] memory bundleLpFees,\n int256[] memory netSendAmounts,\n int256[] memory runningBalances,\n uint8 leafId,\n address[] memory l1Tokens,\n bytes32[] memory proof\n ) external;\n\n function disputeRootBundle() external;\n\n function claimProtocolFeesCaptured(address l1Token) external;\n\n function setPoolRebalanceRoute(\n uint256 destinationChainId,\n address l1Token,\n address destinationToken\n ) external;\n\n function setDepositRoute(\n uint256 originChainId,\n uint256 destinationChainId,\n address originToken,\n bool depositsEnabled\n ) external;\n\n function poolRebalanceRoute(uint256 destinationChainId, address l1Token)\n external\n view\n returns (address destinationToken);\n\n function loadEthForL2Calls() external payable;\n}\n" + }, + "contracts/interfaces/LpTokenFactoryInterface.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @notice Factory to create new LP ERC20 tokens that represent a liquidity provider's position. HubPool is the\n * intended client of this contract.\n */\ninterface LpTokenFactoryInterface {\n /**\n * @notice Deploys new LP token for L1 token. Sets caller as minter and burner of token.\n * @param l1Token L1 token to name in LP token name.\n * @return address of new LP token.\n */\n function createLpToken(address l1Token) external returns (address);\n}\n" + }, + "contracts/interfaces/SpokePoolInterface.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @notice Contains common data structures and functions used by all SpokePool implementations.\n */\ninterface SpokePoolInterface {\n // This leaf is meant to be decoded in the SpokePool to pay out successful relayers.\n struct RelayerRefundLeaf {\n // This is the amount to return to the HubPool. This occurs when there is a PoolRebalanceLeaf netSendAmount that\n // is negative. This is just the negative of this value.\n uint256 amountToReturn;\n // Used to verify that this is being executed on the correct destination chainId.\n uint256 chainId;\n // This array designates how much each of those addresses should be refunded.\n uint256[] refundAmounts;\n // Used as the index in the bitmap to track whether this leaf has been executed or not.\n uint32 leafId;\n // The associated L2TokenAddress that these claims apply to.\n address l2TokenAddress;\n // Must be same length as refundAmounts and designates each address that must be refunded.\n address[] refundAddresses;\n }\n\n // Stores collection of merkle roots that can be published to this contract from the HubPool, which are referenced\n // by \"data workers\" via inclusion proofs to execute leaves in the roots.\n struct RootBundle {\n // Merkle root of slow relays that were not fully filled and whose recipient is still owed funds from the LP pool.\n bytes32 slowRelayRoot;\n // Merkle root of relayer refunds for successful relays.\n bytes32 relayerRefundRoot;\n // This is a 2D bitmap tracking which leaves in the relayer refund root have been claimed, with max size of\n // 256x(2^248) leaves per root.\n mapping(uint256 => uint256) claimedBitmap;\n }\n\n function setCrossDomainAdmin(address newCrossDomainAdmin) external;\n\n function setHubPool(address newHubPool) external;\n\n function setEnableRoute(\n address originToken,\n uint256 destinationChainId,\n bool enable\n ) external;\n\n function pauseDeposits(bool pause) external;\n\n function pauseFills(bool pause) external;\n\n function relayRootBundle(bytes32 relayerRefundRoot, bytes32 slowRelayRoot) external;\n\n function emergencyDeleteRootBundle(uint256 rootBundleId) external;\n\n function deposit(\n address recipient,\n address originToken,\n uint256 amount,\n uint256 destinationChainId,\n int64 relayerFeePct,\n uint32 quoteTimestamp,\n bytes memory message,\n uint256 maxCount\n ) external payable;\n\n function depositFor(\n address depositor,\n address recipient,\n address originToken,\n uint256 amount,\n uint256 destinationChainId,\n int64 relayerFeePct,\n uint32 quoteTimestamp,\n bytes memory message,\n uint256 maxCount\n ) external payable;\n\n function executeRelayerRefundLeaf(\n uint32 rootBundleId,\n SpokePoolInterface.RelayerRefundLeaf memory relayerRefundLeaf,\n bytes32[] memory proof\n ) external payable;\n\n function chainId() external view returns (uint256);\n\n error NotEOA();\n error InvalidDepositorSignature();\n error InvalidRelayerFeePct();\n error MaxTransferSizeExceeded();\n error InvalidCrossDomainAdmin();\n error InvalidHubPool();\n error DepositsArePaused();\n error FillsArePaused();\n}\n" + }, + "contracts/interfaces/SpokePoolMessageHandler.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n// This interface is expected to be implemented by any contract that expects to receive messages from the SpokePool.\ninterface AcrossMessageHandler {\n function handleV3AcrossMessage(\n address tokenSent,\n uint256 amount,\n address relayer,\n bytes memory message\n ) external;\n}\n" + }, + "contracts/interfaces/V3SpokePoolInterface.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n// Contains structs and functions used by SpokePool contracts to facilitate universal settlement.\ninterface V3SpokePoolInterface {\n /**************************************\n * ENUMS *\n **************************************/\n\n // Fill status tracks on-chain state of deposit, uniquely identified by relayHash.\n enum FillStatus {\n Unfilled,\n RequestedSlowFill,\n Filled\n }\n // Fill type is emitted in the FilledRelay event to assist Dataworker with determining which types of\n // fills to refund (e.g. only fast fills) and whether a fast fill created a sow fill excess.\n enum FillType {\n FastFill,\n // Fast fills are normal fills that do not replace a slow fill request.\n ReplacedSlowFill,\n // Replaced slow fills are fast fills that replace a slow fill request. This type is used by the Dataworker\n // to know when to send excess funds from the SpokePool to the HubPool because they can no longer be used\n // for a slow fill execution.\n SlowFill\n // Slow fills are requested via requestSlowFill and executed by executeSlowRelayLeaf after a bundle containing\n // the slow fill is validated.\n }\n\n /**************************************\n * STRUCTS *\n **************************************/\n\n // This struct represents the data to fully specify a **unique** relay submitted on this chain.\n // This data is hashed with the chainId() and saved by the SpokePool to prevent collisions and protect against\n // replay attacks on other chains. If any portion of this data differs, the relay is considered to be\n // completely distinct.\n struct V3RelayData {\n // The address that made the deposit on the origin chain.\n address depositor;\n // The recipient address on the destination chain.\n address recipient;\n // This is the exclusive relayer who can fill the deposit before the exclusivity deadline.\n address exclusiveRelayer;\n // Token that is deposited on origin chain by depositor.\n address inputToken;\n // Token that is received on destination chain by recipient.\n address outputToken;\n // The amount of input token deposited by depositor.\n uint256 inputAmount;\n // The amount of output token to be received by recipient.\n uint256 outputAmount;\n // Origin chain id.\n uint256 originChainId;\n // The id uniquely identifying this deposit on the origin chain.\n uint32 depositId;\n // The timestamp on the destination chain after which this deposit can no longer be filled.\n uint32 fillDeadline;\n // The timestamp on the destination chain after which any relayer can fill the deposit.\n uint32 exclusivityDeadline;\n // Data that is forwarded to the recipient.\n bytes message;\n }\n\n // Contains parameters passed in by someone who wants to execute a slow relay leaf.\n struct V3SlowFill {\n V3RelayData relayData;\n uint256 chainId;\n uint256 updatedOutputAmount;\n }\n\n // Contains information about a relay to be sent along with additional information that is not unique to the\n // relay itself but is required to know how to process the relay. For example, \"updatedX\" fields can be used\n // by the relayer to modify fields of the relay with the depositor's permission, and \"repaymentChainId\" is specified\n // by the relayer to determine where to take a relayer refund, but doesn't affect the uniqueness of the relay.\n struct V3RelayExecutionParams {\n V3RelayData relay;\n bytes32 relayHash;\n uint256 updatedOutputAmount;\n address updatedRecipient;\n bytes updatedMessage;\n uint256 repaymentChainId;\n }\n\n // Packs together parameters emitted in FilledV3Relay because there are too many emitted otherwise.\n // Similar to V3RelayExecutionParams, these parameters are not used to uniquely identify the deposit being\n // filled so they don't have to be unpacked by all clients.\n struct V3RelayExecutionEventInfo {\n address updatedRecipient;\n bytes updatedMessage;\n uint256 updatedOutputAmount;\n FillType fillType;\n }\n\n /**************************************\n * EVENTS *\n **************************************/\n\n event V3FundsDeposited(\n address inputToken,\n address outputToken,\n uint256 inputAmount,\n uint256 outputAmount,\n uint256 indexed destinationChainId,\n uint32 indexed depositId,\n uint32 quoteTimestamp,\n uint32 fillDeadline,\n uint32 exclusivityDeadline,\n address indexed depositor,\n address recipient,\n address exclusiveRelayer,\n bytes message\n );\n\n event RequestedSpeedUpV3Deposit(\n uint256 updatedOutputAmount,\n uint32 indexed depositId,\n address indexed depositor,\n address updatedRecipient,\n bytes updatedMessage,\n bytes depositorSignature\n );\n\n event FilledV3Relay(\n address inputToken,\n address outputToken,\n uint256 inputAmount,\n uint256 outputAmount,\n uint256 repaymentChainId,\n uint256 indexed originChainId,\n uint32 indexed depositId,\n uint32 fillDeadline,\n uint32 exclusivityDeadline,\n address exclusiveRelayer,\n address indexed relayer,\n address depositor,\n address recipient,\n bytes message,\n V3RelayExecutionEventInfo relayExecutionInfo\n );\n\n event RequestedV3SlowFill(\n address inputToken,\n address outputToken,\n uint256 inputAmount,\n uint256 outputAmount,\n uint256 indexed originChainId,\n uint32 indexed depositId,\n uint32 fillDeadline,\n uint32 exclusivityDeadline,\n address exclusiveRelayer,\n address depositor,\n address recipient,\n bytes message\n );\n\n /**************************************\n * FUNCTIONS *\n **************************************/\n\n function depositV3(\n address depositor,\n address recipient,\n address inputToken,\n address outputToken,\n uint256 inputAmount,\n uint256 outputAmount,\n uint256 destinationChainId,\n address exclusiveRelayer,\n uint32 quoteTimestamp,\n uint32 fillDeadline,\n uint32 exclusivityDeadline,\n bytes calldata message\n ) external payable;\n\n function depositV3Now(\n address depositor,\n address recipient,\n address inputToken,\n address outputToken,\n uint256 inputAmount,\n uint256 outputAmount,\n uint256 destinationChainId,\n address exclusiveRelayer,\n uint32 fillDeadlineOffset,\n uint32 exclusivityDeadline,\n bytes calldata message\n ) external payable;\n\n function speedUpV3Deposit(\n address depositor,\n uint32 depositId,\n uint256 updatedOutputAmount,\n address updatedRecipient,\n bytes calldata updatedMessage,\n bytes calldata depositorSignature\n ) external;\n\n function fillV3Relay(V3RelayData calldata relayData, uint256 repaymentChainId) external;\n\n function fillV3RelayWithUpdatedDeposit(\n V3RelayData calldata relayData,\n uint256 repaymentChainId,\n uint256 updatedOutputAmount,\n address updatedRecipient,\n bytes calldata updatedMessage,\n bytes calldata depositorSignature\n ) external;\n\n function requestV3SlowFill(V3RelayData calldata relayData) external;\n\n function executeV3SlowRelayLeaf(\n V3SlowFill calldata slowFillLeaf,\n uint32 rootBundleId,\n bytes32[] calldata proof\n ) external;\n\n /**************************************\n * ERRORS *\n **************************************/\n\n error DisabledRoute();\n error InvalidQuoteTimestamp();\n error InvalidFillDeadline();\n error InvalidExclusiveRelayer();\n error InvalidExclusivityDeadline();\n error MsgValueDoesNotMatchInputAmount();\n error NotExclusiveRelayer();\n error NoSlowFillsInExclusivityWindow();\n error RelayFilled();\n error InvalidSlowFillRequest();\n error ExpiredFillDeadline();\n error InvalidMerkleProof();\n error InvalidChainId();\n error InvalidMerkleLeaf();\n error ClaimedMerkleLeaf();\n error InvalidPayoutAdjustmentPct();\n}\n" + }, + "contracts/libraries/CircleCCTPAdapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"../external/interfaces/CCTPInterfaces.sol\";\n\nlibrary CircleDomainIds {\n uint32 public constant Ethereum = 0;\n uint32 public constant Optimism = 2;\n uint32 public constant Arbitrum = 3;\n uint32 public constant Base = 6;\n uint32 public constant Polygon = 7;\n // Use this value for placeholder purposes only for adapters that extend this adapter but haven't yet been\n // assigned a domain ID by Circle.\n uint32 public constant UNINTIALIZED = type(uint32).max;\n}\n\n/**\n * @notice Facilitate bridging USDC via Circle's CCTP.\n * @dev This contract is intended to be inherited by other chain-specific adapters and spoke pools.\n * @custom:security-contact bugs@across.to\n */\nabstract contract CircleCCTPAdapter {\n using SafeERC20 for IERC20;\n\n /**\n * @notice The domain ID that CCTP will transfer funds to.\n * @dev This identifier is assigned by Circle and is not related to a chain ID.\n * @dev Official domain list can be found here: https://developers.circle.com/stablecoins/docs/supported-domains\n */\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint32 public immutable recipientCircleDomainId;\n\n /**\n * @notice The official USDC contract address on this chain.\n * @dev Posted officially here: https://developers.circle.com/stablecoins/docs/usdc-on-main-networks\n */\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IERC20 public immutable usdcToken;\n\n /**\n * @notice The official Circle CCTP token bridge contract endpoint.\n * @dev Posted officially here: https://developers.circle.com/stablecoins/docs/evm-smart-contracts\n */\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ITokenMessenger public immutable cctpTokenMessenger;\n\n /**\n * @notice intiailizes the CircleCCTPAdapter contract.\n * @param _usdcToken USDC address on the current chain.\n * @param _cctpTokenMessenger TokenMessenger contract to bridge via CCTP. If the zero address is passed, CCTP bridging will be disabled.\n * @param _recipientCircleDomainId The domain ID that CCTP will transfer funds to.\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n IERC20 _usdcToken,\n ITokenMessenger _cctpTokenMessenger,\n uint32 _recipientCircleDomainId\n ) {\n usdcToken = _usdcToken;\n cctpTokenMessenger = _cctpTokenMessenger;\n recipientCircleDomainId = _recipientCircleDomainId;\n }\n\n /**\n * @notice converts address to bytes32 (alignment preserving cast.)\n * @param addr the address to convert to bytes32\n * @dev Sourced from the official CCTP repo: https://github.com/walkerq/evm-cctp-contracts/blob/139d8d0ce3b5531d3c7ec284f89d946dfb720016/src/messages/Message.sol#L142C1-L148C6\n */\n function _addressToBytes32(address addr) internal pure returns (bytes32) {\n return bytes32(uint256(uint160(addr)));\n }\n\n /**\n * @notice Returns whether or not the CCTP bridge is enabled.\n * @dev If the CCTPTokenMessenger is the zero address, CCTP bridging is disabled.\n */\n function _isCCTPEnabled() internal view returns (bool) {\n return address(cctpTokenMessenger) != address(0);\n }\n\n /**\n * @notice Transfers USDC from the current domain to the given address on the new domain.\n * @dev This function will revert if the CCTP bridge is disabled. I.e. if the zero address is passed to the constructor for the cctpTokenMessenger.\n * @param to Address to receive USDC on the new domain.\n * @param amount Amount of USDC to transfer.\n */\n function _transferUsdc(address to, uint256 amount) internal {\n // Only approve the exact amount to be transferred\n usdcToken.safeIncreaseAllowance(address(cctpTokenMessenger), amount);\n // Submit the amount to be transferred to bridged via the TokenMessenger.\n // If the amount to send exceeds the burn limit per message, then split the message into smaller parts.\n ITokenMinter cctpMinter = cctpTokenMessenger.localMinter();\n uint256 burnLimit = cctpMinter.burnLimitsPerMessage(address(usdcToken));\n uint256 remainingAmount = amount;\n bytes32 recipient = _addressToBytes32(to);\n while (remainingAmount > 0) {\n uint256 partAmount = remainingAmount > burnLimit ? burnLimit : remainingAmount;\n cctpTokenMessenger.depositForBurn(partAmount, recipientCircleDomainId, recipient, address(usdcToken));\n remainingAmount -= partAmount;\n }\n }\n}\n" + }, + "contracts/Lockable.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @title A contract that provides modifiers to prevent reentrancy to state-changing and view-only methods. This contract\n * is inspired by https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuard.sol\n * and https://github.com/balancer-labs/balancer-core/blob/master/contracts/BPool.sol.\n * @dev The reason why we use this local contract instead of importing from uma/contracts is because of the addition\n * of the internal method `functionCallStackOriginatesFromOutsideThisContract` which doesn't exist in the one exported\n * by uma/contracts.\n * @custom:security-contact bugs@across.to\n */\ncontract Lockable {\n bool internal _notEntered;\n\n constructor() {\n // Storing an initial non-zero value makes deployment a bit more expensive, but in exchange the refund on every\n // call to nonReentrant will be lower in amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to increase the likelihood of the full\n // refund coming into effect.\n _notEntered = true;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a nonReentrant function from another nonReentrant function is not supported. It is possible to\n * prevent this from happening by making the nonReentrant function external, and making it call a private\n * function that does the actual state modification.\n */\n modifier nonReentrant() {\n _preEntranceCheck();\n _preEntranceSet();\n _;\n _postEntranceReset();\n }\n\n /**\n * @dev Designed to prevent a view-only method from being re-entered during a call to a nonReentrant() state-changing method.\n */\n modifier nonReentrantView() {\n _preEntranceCheck();\n _;\n }\n\n /**\n * @dev Returns true if the contract is currently in a non-entered state, meaning that the origination of the call\n * came from outside the contract. This is relevant with fallback/receive methods to see if the call came from ETH\n * being dropped onto the contract externally or due to ETH dropped on the contract from within a method in this\n * contract, such as unwrapping WETH to ETH within the contract.\n */\n function functionCallStackOriginatesFromOutsideThisContract() internal view returns (bool) {\n return _notEntered;\n }\n\n // Internal methods are used to avoid copying the require statement's bytecode to every nonReentrant() method.\n // On entry into a function, _preEntranceCheck() should always be called to check if the function is being\n // re-entered. Then, if the function modifies state, it should call _postEntranceSet(), perform its logic, and\n // then call _postEntranceReset().\n // View-only methods can simply call _preEntranceCheck() to make sure that it is not being re-entered.\n function _preEntranceCheck() internal view {\n // On the first call to nonReentrant, _notEntered will be true\n require(_notEntered, \"ReentrancyGuard: reentrant call\");\n }\n\n function _preEntranceSet() internal {\n // Any calls to nonReentrant after this point will fail\n _notEntered = false;\n }\n\n function _postEntranceReset() internal {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _notEntered = true;\n }\n}\n" + }, + "contracts/LpTokenFactory.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/LpTokenFactoryInterface.sol\";\n\nimport \"@uma/core/contracts/common/implementation/ExpandedERC20.sol\";\n\n/**\n * @notice Factory to create new LP ERC20 tokens that represent a liquidity provider's position. HubPool is the\n * intended client of this contract.\n * @custom:security-contact bugs@across.to\n */\ncontract LpTokenFactory is LpTokenFactoryInterface {\n /**\n * @notice Deploys new LP token for L1 token. Sets caller as minter and burner of token.\n * @param l1Token L1 token to name in LP token name.\n * @return address of new LP token.\n */\n function createLpToken(address l1Token) public returns (address) {\n ExpandedERC20 lpToken = new ExpandedERC20(\n _concatenate(\"Across V2 \", IERC20Metadata(l1Token).name(), \" LP Token\"), // LP Token Name\n _concatenate(\"Av2-\", IERC20Metadata(l1Token).symbol(), \"-LP\"), // LP Token Symbol\n IERC20Metadata(l1Token).decimals() // LP Token Decimals\n );\n\n lpToken.addMinter(msg.sender); // Set the caller as the LP Token's minter.\n lpToken.addBurner(msg.sender); // Set the caller as the LP Token's burner.\n lpToken.resetOwner(msg.sender); // Set the caller as the LP Token's owner.\n\n return address(lpToken);\n }\n\n function _concatenate(\n string memory a,\n string memory b,\n string memory c\n ) internal pure returns (string memory) {\n return string(abi.encodePacked(a, b, c));\n }\n}\n" + }, + "contracts/merkle-distributor/AcrossMerkleDistributor.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"@uma/core/contracts/merkle-distributor/implementation/MerkleDistributor.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @title Extended MerkleDistributor contract.\n * @notice Adds additional constraints governing who can claim leaves from merkle windows.\n * @custom:security-contact bugs@across.to\n */\ncontract AcrossMerkleDistributor is MerkleDistributor {\n using SafeERC20 for IERC20;\n\n // Addresses that can claim on user's behalf.\n mapping(address => bool) public whitelistedClaimers;\n\n /****************************************\n * EVENTS\n ****************************************/\n event WhitelistedClaimer(address indexed claimer, bool indexed whitelist);\n event ClaimFor(\n address indexed caller,\n uint256 windowIndex,\n address indexed account,\n uint256 accountIndex,\n uint256 amount,\n address indexed rewardToken\n );\n\n /****************************\n * ADMIN FUNCTIONS\n ****************************/\n\n /**\n * @notice Updates whitelisted claimer status.\n * @dev Callable only by owner.\n * @param newContract Reset claimer contract to this address.\n * @param whitelist True to whitelist claimer, False otherwise.\n */\n function whitelistClaimer(address newContract, bool whitelist) external onlyOwner {\n whitelistedClaimers[newContract] = whitelist;\n emit WhitelistedClaimer(newContract, whitelist);\n }\n\n /****************************\n * NON-ADMIN FUNCTIONS\n ****************************/\n\n /**\n * @notice Batch claims to reduce gas versus individual submitting all claims. Method will fail\n * if any individual claims within the batch would fail.\n * @dev All claim recipients must be equal to msg.sender.\n * @param claims array of claims to claim.\n */\n function claimMulti(Claim[] memory claims) public override {\n uint256 claimCount = claims.length;\n for (uint256 i = 0; i < claimCount; i++) {\n require(claims[i].account == msg.sender, \"invalid claimer\");\n }\n super.claimMulti(claims);\n }\n\n /**\n * @notice Claim amount of reward tokens for account, as described by Claim input object.\n * @dev Claim recipient must be equal to msg.sender.\n * @param _claim claim object describing amount, accountIndex, account, window index, and merkle proof.\n */\n function claim(Claim memory _claim) public override {\n require(_claim.account == msg.sender, \"invalid claimer\");\n super.claim(_claim);\n }\n\n /**\n * @notice Executes merkle leaf claim on behaf of user. This can only be called by a trusted\n * claimer address. This function is designed to be called atomically with other transactions\n * that ultimately return the claimed amount to the rightful recipient. For example,\n * AcceleratingDistributor could call this function and then stake atomically on behalf of the user.\n * @dev Caller must be in whitelistedClaimers struct set to \"true\".\n * @param _claim leaf to claim.\n */\n\n function claimFor(Claim memory _claim) public {\n require(whitelistedClaimers[msg.sender], \"unwhitelisted claimer\");\n _verifyAndMarkClaimed(_claim);\n merkleWindows[_claim.windowIndex].rewardToken.safeTransfer(msg.sender, _claim.amount);\n emit ClaimFor(\n msg.sender,\n _claim.windowIndex,\n _claim.account,\n _claim.accountIndex,\n _claim.amount,\n address(merkleWindows[_claim.windowIndex].rewardToken)\n );\n }\n}\n" + }, + "contracts/MerkleLib.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./interfaces/SpokePoolInterface.sol\";\nimport \"./interfaces/V3SpokePoolInterface.sol\";\nimport \"./interfaces/HubPoolInterface.sol\";\n\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\n\n/**\n * @notice Library to help with merkle roots, proofs, and claims.\n * @custom:security-contact bugs@across.to\n */\nlibrary MerkleLib {\n /**\n * @notice Verifies that a repayment is contained within a merkle root.\n * @param root the merkle root.\n * @param rebalance the rebalance struct.\n * @param proof the merkle proof.\n * @return bool to signal if the pool rebalance proof correctly shows inclusion of the rebalance within the tree.\n */\n function verifyPoolRebalance(\n bytes32 root,\n HubPoolInterface.PoolRebalanceLeaf memory rebalance,\n bytes32[] memory proof\n ) internal pure returns (bool) {\n return MerkleProof.verify(proof, root, keccak256(abi.encode(rebalance)));\n }\n\n /**\n * @notice Verifies that a relayer refund is contained within a merkle root.\n * @param root the merkle root.\n * @param refund the refund struct.\n * @param proof the merkle proof.\n * @return bool to signal if the relayer refund proof correctly shows inclusion of the refund within the tree.\n */\n function verifyRelayerRefund(\n bytes32 root,\n SpokePoolInterface.RelayerRefundLeaf memory refund,\n bytes32[] memory proof\n ) internal pure returns (bool) {\n return MerkleProof.verify(proof, root, keccak256(abi.encode(refund)));\n }\n\n function verifyV3SlowRelayFulfillment(\n bytes32 root,\n V3SpokePoolInterface.V3SlowFill memory slowRelayFulfillment,\n bytes32[] memory proof\n ) internal pure returns (bool) {\n return MerkleProof.verify(proof, root, keccak256(abi.encode(slowRelayFulfillment)));\n }\n\n // The following functions are primarily copied from\n // https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol with minor changes.\n\n /**\n * @notice Tests whether a claim is contained within a claimedBitMap mapping.\n * @param claimedBitMap a simple uint256 mapping in storage used as a bitmap.\n * @param index the index to check in the bitmap.\n * @return bool indicating if the index within the claimedBitMap has been marked as claimed.\n */\n function isClaimed(mapping(uint256 => uint256) storage claimedBitMap, uint256 index) internal view returns (bool) {\n uint256 claimedWordIndex = index / 256;\n uint256 claimedBitIndex = index % 256;\n uint256 claimedWord = claimedBitMap[claimedWordIndex];\n uint256 mask = (1 << claimedBitIndex);\n return claimedWord & mask == mask;\n }\n\n /**\n * @notice Marks an index in a claimedBitMap as claimed.\n * @param claimedBitMap a simple uint256 mapping in storage used as a bitmap.\n * @param index the index to mark in the bitmap.\n */\n function setClaimed(mapping(uint256 => uint256) storage claimedBitMap, uint256 index) internal {\n uint256 claimedWordIndex = index / 256;\n uint256 claimedBitIndex = index % 256;\n claimedBitMap[claimedWordIndex] = claimedBitMap[claimedWordIndex] | (1 << claimedBitIndex);\n }\n\n /**\n * @notice Tests whether a claim is contained within a 1D claimedBitMap mapping.\n * @param claimedBitMap a simple uint256 value, encoding a 1D bitmap.\n * @param index the index to check in the bitmap. Uint8 type enforces that index can't be > 255.\n * @return bool indicating if the index within the claimedBitMap has been marked as claimed.\n */\n function isClaimed1D(uint256 claimedBitMap, uint8 index) internal pure returns (bool) {\n uint256 mask = (1 << index);\n return claimedBitMap & mask == mask;\n }\n\n /**\n * @notice Marks an index in a claimedBitMap as claimed.\n * @param claimedBitMap a simple uint256 mapping in storage used as a bitmap. Uint8 type enforces that index\n * can't be > 255.\n * @param index the index to mark in the bitmap.\n * @return uint256 representing the modified input claimedBitMap with the index set to true.\n */\n function setClaimed1D(uint256 claimedBitMap, uint8 index) internal pure returns (uint256) {\n return claimedBitMap | (1 << index);\n }\n}\n" + }, + "contracts/Mode_SpokePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\nimport \"@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol\";\n\nimport \"./Ovm_SpokePool.sol\";\nimport \"./external/interfaces/CCTPInterfaces.sol\";\n\n/**\n * @notice Mode Spoke pool.\n * @custom:security-contact bugs@across.to\n */\ncontract Mode_SpokePool is Ovm_SpokePool {\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeTokenAddress,\n uint32 _depositQuoteTimeBuffer,\n uint32 _fillDeadlineBuffer,\n IERC20 _l2Usdc,\n ITokenMessenger _cctpTokenMessenger\n )\n Ovm_SpokePool(\n _wrappedNativeTokenAddress,\n _depositQuoteTimeBuffer,\n _fillDeadlineBuffer,\n _l2Usdc,\n _cctpTokenMessenger\n )\n {} // solhint-disable-line no-empty-blocks\n\n /**\n * @notice Construct the OVM Mode SpokePool.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n */\n function initialize(\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool\n ) public initializer {\n __OvmSpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool, Lib_PredeployAddresses.OVM_ETH);\n }\n}\n" + }, + "contracts/Optimism_SpokePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\nimport \"@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol\";\n\nimport \"./Ovm_SpokePool.sol\";\nimport \"./external/interfaces/CCTPInterfaces.sol\";\n\n// https://github.com/Synthetixio/synthetix/blob/5ca27785fad8237fb0710eac01421cafbbd69647/contracts/SynthetixBridgeToBase.sol#L50\ninterface SynthetixBridgeToBase {\n function withdrawTo(address to, uint256 amount) external;\n}\n\n/**\n * @notice Optimism Spoke pool.\n * @custom:security-contact bugs@across.to\n */\ncontract Optimism_SpokePool is Ovm_SpokePool {\n // Address of custom bridge used to bridge Synthetix-related assets like SNX.\n address private constant SYNTHETIX_BRIDGE = 0x136b1EC699c62b0606854056f02dC7Bb80482d63;\n\n // Address of SNX ERC20\n address private constant SNX = 0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4;\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeTokenAddress,\n uint32 _depositQuoteTimeBuffer,\n uint32 _fillDeadlineBuffer,\n IERC20 _l2Usdc,\n ITokenMessenger _cctpTokenMessenger\n )\n Ovm_SpokePool(\n _wrappedNativeTokenAddress,\n _depositQuoteTimeBuffer,\n _fillDeadlineBuffer,\n _l2Usdc,\n _cctpTokenMessenger\n )\n {} // solhint-disable-line no-empty-blocks\n\n /**\n * @notice Construct the OVM Optimism SpokePool.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n */\n function initialize(\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool\n ) public initializer {\n __OvmSpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool, Lib_PredeployAddresses.OVM_ETH);\n }\n\n function _bridgeTokensToHubPool(uint256 amountToReturn, address l2TokenAddress) internal virtual override {\n // Handle custom SNX bridge which doesn't conform to the standard bridge interface.\n if (l2TokenAddress == SNX)\n SynthetixBridgeToBase(SYNTHETIX_BRIDGE).withdrawTo(\n hubPool, // _to. Withdraw, over the bridge, to the l1 pool contract.\n amountToReturn // _amount.\n );\n else super._bridgeTokensToHubPool(amountToReturn, l2TokenAddress);\n }\n}\n" + }, + "contracts/Ovm_SpokePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./SpokePool.sol\";\nimport \"./external/interfaces/WETH9Interface.sol\";\nimport \"./libraries/CircleCCTPAdapter.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/crosschain/optimism/LibOptimismUpgradeable.sol\";\nimport \"@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol\";\n\n// https://github.com/ethereum-optimism/optimism/blob/bf51c4935261634120f31827c3910aa631f6bf9c/packages/contracts-bedrock/contracts/L2/L2StandardBridge.sol\ninterface IL2ERC20Bridge {\n function withdrawTo(\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable;\n\n function bridgeERC20To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _amount,\n uint256 _minGasLimit,\n bytes calldata _extraData\n ) external;\n}\n\n/**\n * @notice OVM specific SpokePool. Uses OVM cross-domain-enabled logic to implement admin only access to functions. * Optimism, Base, and Boba each implement this spoke pool and set their chain specific contract addresses for l2Eth and l2Weth.\n * @custom:security-contact bugs@across.to\n */\ncontract Ovm_SpokePool is SpokePool, CircleCCTPAdapter {\n using SafeERC20 for IERC20;\n // \"l1Gas\" parameter used in call to bridge tokens from this contract back to L1 via IL2ERC20Bridge. Currently\n // unused by bridge but included for future compatibility.\n uint32 public l1Gas;\n\n // ETH is an ERC20 on OVM.\n address public l2Eth;\n\n // Address of the Optimism L2 messenger.\n address public constant MESSENGER = Lib_PredeployAddresses.L2_CROSS_DOMAIN_MESSENGER;\n // @dev This storage slot is reserved to replace the old messenger public variable that has now been\n // replaced by the above constant.\n address private __deprecated_messenger;\n\n // Stores alternative token bridges to use for L2 tokens that don't go over the standard bridge. This is needed\n // to support non-standard ERC20 tokens on Optimism, such as DAI which uses a custom bridge with the same\n // interface as the standard bridge.\n mapping(address => address) public tokenBridges;\n\n // Stores mapping of L2 tokens to L1 equivalent tokens. If a mapping is defined for a given L2 token, then\n // the mapped L1 token can be used in _bridgeTokensToHubPool which can then call bridgeERC20To, which\n // requires specfiying an L1 token.\n mapping(address => address) public remoteL1Tokens;\n\n event SetL1Gas(uint32 indexed newL1Gas);\n event SetL2TokenBridge(address indexed l2Token, address indexed tokenBridge);\n event SetRemoteL1Token(address indexed l2Token, address indexed l1Token);\n\n error NotCrossDomainAdmin();\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeTokenAddress,\n uint32 _depositQuoteTimeBuffer,\n uint32 _fillDeadlineBuffer,\n IERC20 _l2Usdc,\n ITokenMessenger _cctpTokenMessenger\n )\n SpokePool(_wrappedNativeTokenAddress, _depositQuoteTimeBuffer, _fillDeadlineBuffer)\n CircleCCTPAdapter(_l2Usdc, _cctpTokenMessenger, CircleDomainIds.Ethereum)\n {} // solhint-disable-line no-empty-blocks\n\n /**\n * @notice Construct the OVM SpokePool.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n * @param _l2Eth Address of L2 ETH token. Usually should be Lib_PreeployAddresses.OVM_ETH but sometimes this can\n * be different, like with Boba which flips the WETH and OVM_ETH addresses.\n */\n function __OvmSpokePool_init(\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool,\n address _l2Eth\n ) public onlyInitializing {\n l1Gas = 5_000_000;\n __SpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool);\n //slither-disable-next-line missing-zero-check\n l2Eth = _l2Eth;\n }\n\n /*******************************************\n * OPTIMISM-SPECIFIC ADMIN FUNCTIONS *\n *******************************************/\n\n /**\n * @notice Change L1 gas limit. Callable only by admin.\n * @param newl1Gas New L1 gas limit to set.\n */\n function setL1GasLimit(uint32 newl1Gas) public onlyAdmin nonReentrant {\n l1Gas = newl1Gas;\n emit SetL1Gas(newl1Gas);\n }\n\n function setRemoteL1Token(address l2Token, address l1Token) public onlyAdmin nonReentrant {\n remoteL1Tokens[l2Token] = l1Token;\n emit SetRemoteL1Token(l2Token, l1Token);\n }\n\n /**\n * @notice Set bridge contract for L2 token used to withdraw back to L1.\n * @dev If this mapping isn't set for an L2 token, then the standard bridge will be used to bridge this token.\n * @param tokenBridge Address of token bridge\n */\n function setTokenBridge(address l2Token, address tokenBridge) public onlyAdmin nonReentrant {\n tokenBridges[l2Token] = tokenBridge;\n emit SetL2TokenBridge(l2Token, tokenBridge);\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n /**\n * @notice Wraps any ETH into WETH before executing leaves. This is necessary because SpokePool receives\n * ETH over the canonical token bridge instead of WETH.\n */\n function _preExecuteLeafHook(address l2TokenAddress) internal override {\n if (l2TokenAddress == address(wrappedNativeToken)) _depositEthToWeth();\n }\n\n // Wrap any ETH owned by this contract so we can send expected L2 token to recipient. This is necessary because\n // this SpokePool will receive ETH from the canonical token bridge instead of WETH. Its not sufficient to execute\n // this logic inside a fallback method that executes when this contract receives ETH because ETH is an ERC20\n // on the OVM.\n function _depositEthToWeth() internal {\n //slither-disable-next-line arbitrary-send-eth\n if (address(this).balance > 0) wrappedNativeToken.deposit{ value: address(this).balance }();\n }\n\n function _bridgeTokensToHubPool(uint256 amountToReturn, address l2TokenAddress) internal virtual override {\n // If the token being bridged is WETH then we need to first unwrap it to ETH and then send ETH over the\n // canonical bridge. On Optimism, this is address 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000.\n if (l2TokenAddress == address(wrappedNativeToken)) {\n WETH9Interface(l2TokenAddress).withdraw(amountToReturn); // Unwrap into ETH.\n l2TokenAddress = l2Eth; // Set the l2TokenAddress to ETH.\n IL2ERC20Bridge(Lib_PredeployAddresses.L2_STANDARD_BRIDGE).withdrawTo{ value: amountToReturn }(\n l2TokenAddress, // _l2Token. Address of the L2 token to bridge over.\n hubPool, // _to. Withdraw, over the bridge, to the l1 pool contract.\n amountToReturn, // _amount.\n l1Gas, // _l1Gas. Unused, but included for potential forward compatibility considerations\n \"\" // _data. We don't need to send any data for the bridging action.\n );\n }\n // If the token is USDC && CCTP bridge is enabled, then bridge USDC via CCTP.\n else if (_isCCTPEnabled() && l2TokenAddress == address(usdcToken)) {\n _transferUsdc(hubPool, amountToReturn);\n }\n // Note we'll default to withdrawTo instead of bridgeERC20To unless the remoteL1Tokens mapping is set for\n // the l2TokenAddress. withdrawTo should be used to bridge back non-native L2 tokens\n // (i.e. non-native L2 tokens have a canonical L1 token). If we should bridge \"native L2\" tokens then\n // we'd need to call bridgeERC20To and give allowance to the tokenBridge to spend l2Token from this contract.\n // Therefore for native tokens we should set ensure that remoteL1Tokens is set for the l2TokenAddress.\n else {\n IL2ERC20Bridge tokenBridge = IL2ERC20Bridge(\n tokenBridges[l2TokenAddress] == address(0)\n ? Lib_PredeployAddresses.L2_STANDARD_BRIDGE\n : tokenBridges[l2TokenAddress]\n );\n if (remoteL1Tokens[l2TokenAddress] != address(0)) {\n // If there is a mapping for this L2 token to an L1 token, then use the L1 token address and\n // call bridgeERC20To.\n IERC20(l2TokenAddress).safeIncreaseAllowance(address(tokenBridge), amountToReturn);\n address remoteL1Token = remoteL1Tokens[l2TokenAddress];\n tokenBridge.bridgeERC20To(\n l2TokenAddress, // _l2Token. Address of the L2 token to bridge over.\n remoteL1Token, // Remote token to be received on L1 side. If the\n // remoteL1Token on the other chain does not recognize the local token as the correct\n // pair token, the ERC20 bridge will fail and the tokens will be returned to sender on\n // this chain.\n hubPool, // _to\n amountToReturn, // _amount\n l1Gas, // _l1Gas\n \"\" // _data\n );\n } else {\n tokenBridge.withdrawTo(\n l2TokenAddress, // _l2Token. Address of the L2 token to bridge over.\n hubPool, // _to. Withdraw, over the bridge, to the l1 pool contract.\n amountToReturn, // _amount.\n l1Gas, // _l1Gas. Unused, but included for potential forward compatibility considerations\n \"\" // _data. We don't need to send any data for the bridging action.\n );\n }\n }\n }\n\n // Apply OVM-specific transformation to cross domain admin address on L1.\n function _requireAdminSender() internal view override {\n if (LibOptimismUpgradeable.crossChainSender(MESSENGER) != crossDomainAdmin) revert NotCrossDomainAdmin();\n }\n\n // Reserve storage slots for future versions of this base contract to add state variables without\n // affecting the storage layout of child contracts. Decrement the size of __gap whenever state variables\n // are added. This is at bottom of contract to make sure its always at the end of storage.\n uint256[999] private __gap;\n}\n" + }, + "contracts/PermissionSplitterProxy.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport \"@uma/core/contracts/common/implementation/MultiCaller.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\n/**\n * @notice This contract is designed to own an Ownable \"target\" contract and gate access to specific\n * function selectors based on specific roles. Practically, this contract should own the HubPool contract.\n * All ownable function calls to target should be sent through this contract's fallback function.\n * @custom:security-contact bugs@across.to\n */\ncontract PermissionSplitterProxy is AccessControl, MultiCaller {\n // Inherited admin role from AccessControl. Should be assigned to Across DAO Safe.\n // bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n // Maps function signatures to role identifiers, which gatekeeps access to these functions to\n // only role holders.\n mapping(bytes4 => bytes32) public roleForSelector;\n\n // The contract that should be owned by this contract and whose function selectors will be gated\n // by roleForSelector.\n address public target;\n\n event TargetUpdated(address indexed newTarget);\n event RoleForSelectorSet(bytes4 indexed selector, bytes32 indexed role);\n\n /**\n * @notice constructs PermissionSplitterProxy\n */\n constructor(address _target) {\n _init(_target);\n }\n\n /**\n * @notice Change target contract.\n * @dev Public function! This has two underscores in front to prevent any collisions with the target contract.\n * @dev Only callable by default admin role holder.\n * @param _target New target contract.\n */\n function __setTarget(address _target) public onlyRole(DEFAULT_ADMIN_ROLE) {\n target = _target;\n emit TargetUpdated(_target);\n }\n\n /**\n * @notice Change role ID for function selector. Only role holder can call function selector\n * on target.\n * @dev Public function! This has two underscores in front to prevent any collisions with the target contract.\n * @dev Only callable by default admin role holder.\n * @param selector Function selector to map to role.\n * @param role Only this role holder can call function selector on the target\n */\n function __setRoleForSelector(bytes4 selector, bytes32 role) public onlyRole(DEFAULT_ADMIN_ROLE) {\n roleForSelector[selector] = role;\n emit RoleForSelectorSet(selector, role);\n }\n\n function _init(address _target) internal virtual {\n _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n __setTarget(_target);\n }\n\n function _isAllowedToCall(address caller, bytes calldata callData) internal view virtual returns (bool) {\n bytes4 selector;\n if (callData.length < 4) {\n // This handles any empty callData, which is a call to the fallback function.\n selector = bytes4(0);\n } else {\n selector = bytes4(callData[:4]);\n }\n return hasRole(DEFAULT_ADMIN_ROLE, caller) || hasRole(roleForSelector[selector], caller);\n }\n\n /**\n * @dev Forwards the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n * Note: this function is a modified _delegate function here:\n // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/002a7c8812e73c282b91e14541ce9b93a6de1172/contracts/proxy/Proxy.sol#L22-L45\n */\n function _forward(address _target) internal {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := call(gas(), _target, callvalue(), 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // call returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n // Executes an action on the target.\n function _executeAction() internal virtual {\n require(_isAllowedToCall(msg.sender, msg.data), \"Not allowed to call\");\n _forward(target);\n }\n\n /**\n * @dev Fallback function that forwards calls to the target. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _executeAction();\n }\n\n /**\n * @dev Fallback function that delegates calls to the target. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _executeAction();\n }\n}\n" + }, + "contracts/permit2-order/Permit2Depositor.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./Permit2OrderLib.sol\";\nimport \"../external/interfaces/IPermit2.sol\";\nimport \"../interfaces/V3SpokePoolInterface.sol\";\n\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @notice Permit2Depositor processes an external order type and translates it into an AcrossV3 deposit.\n */\ncontract Permit2Depositor {\n using SafeERC20 for IERC20;\n\n // SpokePool that this contract can deposit to.\n V3SpokePoolInterface public immutable SPOKE_POOL;\n\n // Permit2 contract\n IPermit2 public immutable PERMIT2;\n\n // quoteBeforeDeadline is subtracted from the deadline to get the quote timestamp.\n // This is a somewhat arbitrary conversion, but order creators need some way to precompute the quote timestamp.\n uint256 public immutable QUOTE_BEFORE_DEADLINE;\n\n /**\n * @notice Construct the Permit2Depositor.\n * @param _spokePool SpokePool that this contract can deposit to.\n * @param _permit2 Permit2 contract\n * @param _quoteBeforeDeadline quoteBeforeDeadline is subtracted from the deadline to get the quote timestamp.\n */\n constructor(\n V3SpokePoolInterface _spokePool,\n IPermit2 _permit2,\n uint256 _quoteBeforeDeadline\n ) {\n SPOKE_POOL = _spokePool;\n PERMIT2 = _permit2;\n QUOTE_BEFORE_DEADLINE = _quoteBeforeDeadline;\n }\n\n /**\n * @notice Uses a permit2 order to deposit to a SpokePool.\n * @param signedOrder Signed external order type that is processed to produce the deposit. See Permit2OrderLib for details\n * @param destinationChainFillerAddress Address of the filler on the destination chain. Specified by caller\n * to avoid issue if destination and current network have different address derivation schemes.\n */\n function permit2Deposit(SignedOrder calldata signedOrder, address destinationChainFillerAddress) external {\n CrossChainLimitOrder memory order = Permit2OrderLib._processPermit2Order(PERMIT2, signedOrder);\n uint32 fillDeadline = SafeCast.toUint32(block.timestamp + order.info.fillPeriod);\n\n // User input amount and filler collateral are added together to get the deposit amount.\n // If the user gets filled correctly, the filler gets their collateral back.\n // If the user is not filled or filled by someone else, the filler loses their collateral.\n uint256 amountToDeposit = order.input.amount + order.fillerCollateral.amount;\n\n IERC20(order.input.token).safeIncreaseAllowance(address(SPOKE_POOL), amountToDeposit);\n SPOKE_POOL.depositV3(\n order.info.offerer,\n // Note: Permit2OrderLib checks that order only has a single output.\n order.outputs[0].recipient,\n order.input.token,\n order.outputs[0].token,\n amountToDeposit,\n order.outputs[0].amount,\n order.outputs[0].chainId,\n destinationChainFillerAddress,\n SafeCast.toUint32(order.info.initiateDeadline - QUOTE_BEFORE_DEADLINE),\n fillDeadline,\n // The entire fill period is exclusive.\n fillDeadline,\n \"\"\n );\n }\n}\n" + }, + "contracts/permit2-order/Permit2Order.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\n// General Settlement Info.\nstruct SettlementInfo {\n // The contract intended for settlement.\n address settlerContract;\n // User who created the order.\n address offerer;\n // The nonce of the order for replay protection.\n uint256 nonce;\n // Latest timestamp at which the order can be brought onchain.\n uint256 initiateDeadline;\n // Max delay between the order being brought onchain and the fill.\n uint32 fillPeriod;\n // The rest of the fields are unused in Across.\n uint32 challengePeriod;\n uint32 proofPeriod;\n address settlementOracle;\n address validationContract;\n bytes validationData;\n}\n\n// Input token info.\nstruct InputToken {\n address token;\n uint256 amount;\n uint256 maxAmount;\n}\n\n// Callateral token info.\nstruct CollateralToken {\n address token;\n uint256 amount;\n}\n\n// Output information.\nstruct OutputToken {\n address recipient;\n address token;\n uint256 amount;\n uint256 chainId;\n}\n\n// Full order struct that the user signs.\nstruct CrossChainLimitOrder {\n // General order info.\n SettlementInfo info;\n // User's input token.\n InputToken input;\n // Filler's provided collateral.\n CollateralToken fillerCollateral;\n // Unused in Across.\n CollateralToken challengerCollateral;\n // Outputs. Today, Across only supports a single output.\n OutputToken[] outputs;\n}\n\n// Encoded order + Permit2 signature.\nstruct SignedOrder {\n bytes order;\n bytes sig;\n}\n" + }, + "contracts/permit2-order/Permit2OrderLib.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"./Permit2Order.sol\";\nimport \"../external/interfaces/IPermit2.sol\";\n\n/**\n * @notice Permit2OrderLib knows how to process a particular type of external Permit2Order so that it can be used in Across.\n * @dev This library is responsible for validating the order and communicating with Permit2 to pull the tokens in.\n * This is a library to allow it to be pulled directly into the SpokePool in a future version.\n */\nlibrary Permit2OrderLib {\n // Errors\n error WrongSettlerContract();\n error AfterDeadline();\n error ValidationContractNotAllowed();\n error MultipleOutputsNotAllowed();\n error InputAndCollateralNotEqual();\n\n // Type strings and hashes\n bytes private constant OUTPUT_TOKEN_TYPE =\n \"OutputToken(address recipient,address token,uint256 amount,uint256 chainId)\";\n bytes32 private constant OUTPUT_TOKEN_TYPE_HASH = keccak256(OUTPUT_TOKEN_TYPE);\n\n bytes internal constant ORDER_TYPE =\n abi.encodePacked(\n \"CrossChainLimitOrder(\",\n \"address settlerContract,\",\n \"address offerer,\",\n \"uint256 nonce,\",\n \"uint256 initiateDeadline,\",\n \"uint32 fillPeriod\",\n \"uint32 challengePeriod\",\n \"uint32 proofPeriod\",\n \"address settlementOracle\",\n \"address validationContract,\",\n \"bytes validationData,\",\n \"address inputToken,\",\n \"uint256 inputAmount,\",\n \"address collateralToken,\",\n \"uint256 collateralAmount,\",\n \"address challengerCollateralToken,\",\n \"uint256 challengerCollateralAmount,\",\n \"OutputToken[] outputs)\",\n OUTPUT_TOKEN_TYPE\n );\n bytes32 internal constant ORDER_TYPE_HASH = keccak256(ORDER_TYPE);\n string private constant TOKEN_PERMISSIONS_TYPE = \"TokenPermissions(address token,uint256 amount)\";\n string internal constant PERMIT2_ORDER_TYPE =\n string(abi.encodePacked(\"CrossChainLimitOrder witness)\", ORDER_TYPE, TOKEN_PERMISSIONS_TYPE));\n\n // Hashes a single output.\n function _hashOutput(OutputToken memory output) internal pure returns (bytes32) {\n return\n keccak256(\n abi.encode(OUTPUT_TOKEN_TYPE_HASH, output.recipient, output.token, output.amount, output.chainId)\n );\n }\n\n // Hashes the output array. Since we only allow a single output, it just grabs the first element.\n function _hashOutputs(OutputToken[] memory outputs) internal pure returns (bytes32) {\n // Across only allows a single output, so only hash\n return keccak256(abi.encodePacked(_hashOutput(outputs[0])));\n }\n\n // Hashes an order to get an order hash. Needed for permit2.\n function _hashOrder(CrossChainLimitOrder memory order) internal pure returns (bytes32) {\n bytes memory part1 = abi.encode(\n ORDER_TYPE_HASH,\n order.info.settlerContract,\n order.info.offerer,\n order.info.nonce,\n order.info.initiateDeadline,\n order.info.fillPeriod,\n order.info.challengePeriod,\n order.info.proofPeriod,\n order.info.settlementOracle,\n order.info.validationContract,\n keccak256(order.info.validationData),\n order.input.token,\n order.input.amount\n );\n\n // avoid stack too deep\n bytes memory part2 = abi.encode(\n order.fillerCollateral.token,\n order.fillerCollateral.amount,\n order.challengerCollateral.token,\n order.challengerCollateral.amount,\n _hashOutputs(order.outputs)\n );\n\n return keccak256(abi.encodePacked(part1, part2));\n }\n\n function _processPermit2Order(IPermit2 permit2, SignedOrder calldata signedOrder)\n internal\n returns (CrossChainLimitOrder memory)\n {\n CrossChainLimitOrder memory limitOrder = abi.decode(signedOrder.order, (CrossChainLimitOrder));\n\n if (address(this) != limitOrder.info.settlerContract) revert WrongSettlerContract();\n if (block.timestamp > limitOrder.info.initiateDeadline) revert AfterDeadline();\n if (limitOrder.info.validationContract != address(0)) revert ValidationContractNotAllowed();\n if (limitOrder.outputs.length != 1) revert MultipleOutputsNotAllowed();\n if (limitOrder.fillerCollateral.token != limitOrder.input.token) revert InputAndCollateralNotEqual();\n\n IPermit2.PermitTransferFrom memory permit = IPermit2.PermitTransferFrom({\n permitted: IPermit2.TokenPermissions({ token: limitOrder.input.token, amount: limitOrder.input.maxAmount }),\n nonce: limitOrder.info.nonce,\n deadline: limitOrder.info.initiateDeadline\n });\n\n IPermit2.SignatureTransferDetails memory signatureTransferDetails = IPermit2.SignatureTransferDetails({\n to: address(this),\n requestedAmount: limitOrder.input.amount\n });\n\n // Pull user funds.\n permit2.permitWitnessTransferFrom(\n permit,\n signatureTransferDetails,\n limitOrder.info.offerer,\n _hashOrder(limitOrder),\n PERMIT2_ORDER_TYPE,\n signedOrder.sig\n );\n\n // Pull filler collateral.\n permit2.transferFrom(\n msg.sender,\n address(this),\n uint160(limitOrder.fillerCollateral.amount),\n limitOrder.fillerCollateral.token\n );\n\n return limitOrder;\n }\n}\n" + }, + "contracts/Polygon_SpokePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./SpokePool.sol\";\nimport \"./PolygonTokenBridger.sol\";\nimport \"./external/interfaces/WETH9Interface.sol\";\nimport \"./interfaces/SpokePoolInterface.sol\";\nimport \"./libraries/CircleCCTPAdapter.sol\";\n\n/**\n * @notice IFxMessageProcessor represents interface to process messages.\n */\ninterface IFxMessageProcessor {\n /**\n * @notice Called by FxChild upon receiving L1 message that targets this contract. Performs an additional check\n * that the L1 caller was the expected cross domain admin, and then delegate calls.\n * @notice Polygon bridge only executes this external function on the target Polygon contract when relaying\n * messages from L1, so all functions on this SpokePool are expected to originate via this call.\n * @dev stateId value isn't used because it isn't relevant for this method. It doesn't care what state sync\n * triggered this call.\n * @param rootMessageSender Original L1 sender of data.\n * @param data ABI encoded function call to execute on this contract.\n */\n function processMessageFromRoot(\n uint256 stateId,\n address rootMessageSender,\n bytes calldata data\n ) external;\n}\n\n/**\n * @notice Polygon specific SpokePool.\n * @custom:security-contact bugs@across.to\n */\ncontract Polygon_SpokePool is IFxMessageProcessor, SpokePool, CircleCCTPAdapter {\n using SafeERC20Upgradeable for PolygonIERC20Upgradeable;\n\n // Address of FxChild which sends and receives messages to and from L1.\n address public fxChild;\n\n // Contract deployed on L1 and L2 processes all cross-chain transfers between this contract and the HubPool.\n // Required because bridging tokens from Polygon to Ethereum has special constraints.\n PolygonTokenBridger public polygonTokenBridger;\n\n // Internal variable that only flips temporarily to true upon receiving messages from L1. Used to authenticate that\n // the caller is the fxChild AND that the fxChild called processMessageFromRoot\n bool private callValidated;\n\n error MulticallExecuteLeaf();\n\n event SetFxChild(address indexed newFxChild);\n event SetPolygonTokenBridger(address indexed polygonTokenBridger);\n event ReceivedMessageFromL1(address indexed caller, address indexed rootMessageSender);\n\n error CallValidatedAlreadySet();\n error CallValidatedNotSet();\n error DelegateCallFailed();\n error NotHubPool();\n error NotFxChild();\n\n // Note: validating calls this way ensures that strange calls coming from the fxChild won't be misinterpreted.\n // Put differently, just checking that msg.sender == fxChild is not sufficient.\n // All calls that have admin privileges must be fired from within the processMessageFromRoot method that's gone\n // through validation where the sender is checked and the root (mainnet) sender is also validated.\n // This modifier sets the callValidated variable so this condition can be checked in _requireAdminSender().\n modifier validateInternalCalls() {\n // Make sure callValidated is set to True only once at beginning of processMessageFromRoot, which prevents\n // processMessageFromRoot from being re-entered.\n if (callValidated) revert CallValidatedAlreadySet();\n\n // This sets a variable indicating that we're now inside a validated call.\n // Note: this is used by other methods to ensure that this call has been validated by this method and is not\n // spoofed. See comment for `_requireAdminSender` for more details.\n callValidated = true;\n\n _;\n\n // Reset callValidated to false to disallow admin calls after this method exits.\n callValidated = false;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeTokenAddress,\n uint32 _depositQuoteTimeBuffer,\n uint32 _fillDeadlineBuffer,\n IERC20 _l2Usdc,\n ITokenMessenger _cctpTokenMessenger\n )\n SpokePool(_wrappedNativeTokenAddress, _depositQuoteTimeBuffer, _fillDeadlineBuffer)\n CircleCCTPAdapter(_l2Usdc, _cctpTokenMessenger, CircleDomainIds.Ethereum)\n {} // solhint-disable-line no-empty-blocks\n\n /**\n * @notice Construct the Polygon SpokePool.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _polygonTokenBridger Token routing contract that sends tokens from here to HubPool. Changeable by Admin.\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n * @param _fxChild FxChild contract, changeable by Admin.\n */\n function initialize(\n uint32 _initialDepositId,\n PolygonTokenBridger _polygonTokenBridger,\n address _crossDomainAdmin,\n address _hubPool,\n address _fxChild\n ) public initializer {\n callValidated = false;\n __SpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool);\n _setPolygonTokenBridger(payable(_polygonTokenBridger));\n //slither-disable-next-line missing-zero-check\n _setFxChild(_fxChild);\n }\n\n /********************************************************\n * POLYGON-SPECIFIC CROSS-CHAIN ADMIN FUNCTIONS *\n ********************************************************/\n\n /**\n * @notice Change FxChild address. Callable only by admin via processMessageFromRoot.\n * @param newFxChild New FxChild.\n */\n function setFxChild(address newFxChild) public onlyAdmin nonReentrant {\n _setFxChild(newFxChild);\n }\n\n /**\n * @notice Change polygonTokenBridger address. Callable only by admin via processMessageFromRoot.\n * @param newPolygonTokenBridger New Polygon Token Bridger contract.\n */\n function setPolygonTokenBridger(address payable newPolygonTokenBridger) public onlyAdmin nonReentrant {\n _setPolygonTokenBridger(newPolygonTokenBridger);\n }\n\n /**\n * @notice Called by FxChild upon receiving L1 message that targets this contract. Performs an additional check\n * that the L1 caller was the expected cross domain admin, and then delegate calls.\n * @notice Polygon bridge only executes this external function on the target Polygon contract when relaying\n * messages from L1, so all functions on this SpokePool are expected to originate via this call.\n * @dev stateId value isn't used because it isn't relevant for this method. It doesn't care what state sync\n * triggered this call.\n * @param rootMessageSender Original L1 sender of data.\n * @param data ABI encoded function call to execute on this contract.\n */\n function processMessageFromRoot(\n uint256, /*stateId*/\n address rootMessageSender,\n bytes calldata data\n ) public validateInternalCalls {\n // Validation logic.\n if (msg.sender != fxChild) revert NotFxChild();\n if (rootMessageSender != crossDomainAdmin) revert NotHubPool();\n\n // This uses delegatecall to take the information in the message and process it as a function call on this contract.\n /// This is a safe delegatecall because its made to address(this) so there is no risk of delegating to a\n /// selfdestruct().\n //slither-disable-start low-level-calls\n /// @custom:oz-upgrades-unsafe-allow delegatecall\n (bool success, ) = address(this).delegatecall(data);\n //slither-disable-end low-level-calls\n if (!success) revert DelegateCallFailed();\n\n emit ReceivedMessageFromL1(msg.sender, rootMessageSender);\n }\n\n /**\n * @notice Allows the caller to trigger the wrapping of any unwrapped matic tokens.\n * @dev Unlike other ERC20 transfers, Matic transfers from L1 -> L2 bridging don't result in an L2 call into\n * the contract receiving the tokens, so wrapping must be done via a separate transaction. In other words,\n * we can't rely upon a `fallback()` method being triggered to wrap MATIC upon receiving it.\n */\n function wrap() public nonReentrant {\n _wrap();\n }\n\n /**\n * @notice Override multicall so that it cannot include executeRelayerRefundLeaf\n * as one of the calls combined with other public function calls.\n * @dev Multicalling a single transaction will always succeed.\n * @dev Multicalling execute functions without combining other public function calls will succeed.\n * @dev Multicalling public function calls without combining execute functions will succeed.\n */\n function _validateMulticallData(bytes[] calldata data) internal pure override {\n bool hasOtherPublicFunctionCall = false;\n bool hasExecutedLeafCall = false;\n for (uint256 i = 0; i < data.length; i++) {\n bytes4 selector = bytes4(data[i][:4]);\n if (selector == SpokePoolInterface.executeRelayerRefundLeaf.selector) {\n if (hasOtherPublicFunctionCall) revert MulticallExecuteLeaf();\n hasExecutedLeafCall = true;\n } else {\n if (hasExecutedLeafCall) revert MulticallExecuteLeaf();\n hasOtherPublicFunctionCall = true;\n }\n }\n }\n\n /**\n * @notice This function can send an L2 to L1 message so we are extra cautious about preventing a griefing vector\n * whereby someone batches this call with a bunch of other calls and produces a very large L2 burn transaction.\n * This might make the L2 -> L1 message fail due to exceeding the L1 calldata limit.\n */\n\n function executeRelayerRefundLeaf(\n uint32 rootBundleId,\n SpokePoolInterface.RelayerRefundLeaf memory relayerRefundLeaf,\n bytes32[] memory proof\n ) public payable override {\n // AddressLibUpgradeable.isContract isn't a sufficient check because it checks the contract code size of\n // msg.sender which is 0 if called from a constructor function on msg.sender. This is why we check if\n // msg.sender is equal to tx.origin which is fine as long as Polygon supports the tx.origin opcode.\n // solhint-disable-next-line avoid-tx-origin\n if (relayerRefundLeaf.amountToReturn > 0 && msg.sender != tx.origin) revert NotEOA();\n super.executeRelayerRefundLeaf(rootBundleId, relayerRefundLeaf, proof);\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n function _setFxChild(address _fxChild) internal {\n //slither-disable-next-line missing-zero-check\n fxChild = _fxChild;\n emit SetFxChild(_fxChild);\n }\n\n function _setPolygonTokenBridger(address payable _polygonTokenBridger) internal {\n polygonTokenBridger = PolygonTokenBridger(_polygonTokenBridger);\n emit SetPolygonTokenBridger(address(_polygonTokenBridger));\n }\n\n function _preExecuteLeafHook(address) internal override {\n // Wraps MATIC --> WMATIC before distributing tokens from this contract.\n _wrap();\n }\n\n function _bridgeTokensToHubPool(uint256 amountToReturn, address l2TokenAddress) internal override {\n // If the token is USDC, we need to use the CCTP bridge to transfer it to the hub pool.\n if (_isCCTPEnabled() && l2TokenAddress == address(usdcToken)) {\n _transferUsdc(hubPool, amountToReturn);\n } else {\n PolygonIERC20Upgradeable(l2TokenAddress).safeIncreaseAllowance(\n address(polygonTokenBridger),\n amountToReturn\n );\n // Note: WrappedNativeToken is WMATIC on matic, so this tells the tokenbridger that this is an unwrappable native token.\n polygonTokenBridger.send(PolygonIERC20Upgradeable(l2TokenAddress), amountToReturn);\n }\n }\n\n function _wrap() internal {\n uint256 balance = address(this).balance;\n //slither-disable-next-line arbitrary-send-eth\n if (balance > 0) wrappedNativeToken.deposit{ value: balance }();\n }\n\n // @dev: This contract will trigger admin functions internally via the `processMessageFromRoot`, which is why\n // the `callValidated` check is made below and why we use the `validateInternalCalls` modifier on\n // `processMessageFromRoot`. This prevents calling the admin functions from any other method besides\n // `processMessageFromRoot`.\n function _requireAdminSender() internal view override {\n if (!callValidated) revert CallValidatedNotSet();\n }\n}\n" + }, + "contracts/PolygonTokenBridger.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./Lockable.sol\";\nimport \"./external/interfaces/WETH9Interface.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n// Polygon Registry contract that stores their addresses.\ninterface PolygonRegistry {\n function erc20Predicate() external returns (address);\n}\n\n// Polygon ERC20Predicate contract that handles Plasma exits (only used for Matic).\ninterface PolygonERC20Predicate {\n function startExitWithBurntTokens(bytes calldata data) external;\n}\n\n// ERC20s (on polygon) compatible with polygon's bridge have a withdraw method.\ninterface PolygonIERC20Upgradeable is IERC20Upgradeable {\n function withdraw(uint256 amount) external;\n}\n\ninterface MaticToken {\n function withdraw(uint256 amount) external payable;\n}\n\n/**\n * @notice Contract deployed on Ethereum and Polygon to facilitate token transfers from Polygon to the HubPool and back.\n * @dev Because Polygon only allows withdrawals from a particular address to go to that same address on mainnet, we need to\n * have some sort of contract that can guarantee identical addresses on Polygon and Ethereum. This contract is intended\n * to be completely immutable, so it's guaranteed that the contract on each side is configured identically as long as\n * it is created via create2. create2 is an alternative creation method that uses a different address determination\n * mechanism from normal create.\n * Normal create: address = hash(deployer_address, deployer_nonce)\n * create2: address = hash(0xFF, sender, salt, bytecode)\n * This ultimately allows create2 to generate deterministic addresses that don't depend on the transaction count of the\n * sender.\n * @custom:security-contact bugs@across.to\n */\ncontract PolygonTokenBridger is Lockable {\n using SafeERC20Upgradeable for PolygonIERC20Upgradeable;\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n // Gas token for Polygon.\n MaticToken public constant MATIC = MaticToken(0x0000000000000000000000000000000000001010);\n\n // Should be set to HubPool on Ethereum, or unused on Polygon.\n address public immutable destination;\n\n // Registry that stores L1 polygon addresses.\n PolygonRegistry public immutable l1PolygonRegistry;\n\n // WETH contract on Ethereum.\n WETH9Interface public immutable l1Weth;\n\n // Wrapped Matic on Polygon\n address public immutable l2WrappedMatic;\n\n // Chain id for the L1 that this contract is deployed on or communicates with.\n // For example: if this contract were meant to facilitate transfers from polygon to mainnet, this value would be\n // the mainnet chainId 1.\n uint256 public immutable l1ChainId;\n\n // Chain id for the L2 that this contract is deployed on or communicates with.\n // For example: if this contract were meant to facilitate transfers from polygon to mainnet, this value would be\n // the polygon chainId 137.\n uint256 public immutable l2ChainId;\n\n modifier onlyChainId(uint256 chainId) {\n _requireChainId(chainId);\n _;\n }\n\n /**\n * @notice Constructs Token Bridger contract.\n * @param _destination Where to send tokens to for this network.\n * @param _l1PolygonRegistry L1 registry that stores updated addresses of polygon contracts. This should always be\n * set to the L1 registry regardless if whether it's deployed on L2 or L1.\n * @param _l1Weth L1 WETH address.\n * @param _l2WrappedMatic L2 address of wrapped matic token.\n * @param _l1ChainId the chain id for the L1 in this environment.\n * @param _l2ChainId the chain id for the L2 in this environment.\n */\n constructor(\n address _destination,\n PolygonRegistry _l1PolygonRegistry,\n WETH9Interface _l1Weth,\n address _l2WrappedMatic,\n uint256 _l1ChainId,\n uint256 _l2ChainId\n ) {\n //slither-disable-next-line missing-zero-check\n destination = _destination;\n l1PolygonRegistry = _l1PolygonRegistry;\n l1Weth = _l1Weth;\n //slither-disable-next-line missing-zero-check\n l2WrappedMatic = _l2WrappedMatic;\n l1ChainId = _l1ChainId;\n l2ChainId = _l2ChainId;\n }\n\n /**\n * @notice Called by Polygon SpokePool to send tokens over bridge to contract with the same address as this.\n * @notice The caller of this function must approve this contract to spend amount of token.\n * @param token Token to bridge.\n * @param amount Amount to bridge.\n */\n function send(PolygonIERC20Upgradeable token, uint256 amount) public nonReentrant onlyChainId(l2ChainId) {\n token.safeTransferFrom(msg.sender, address(this), amount);\n\n // In the wMatic case, this unwraps. For other ERC20s, this is the burn/send action.\n token.withdraw(token.balanceOf(address(this)));\n\n // This takes the token that was withdrawn and calls withdraw on the \"native\" ERC20.\n if (address(token) == l2WrappedMatic) MATIC.withdraw{ value: address(this).balance }(address(this).balance);\n }\n\n /**\n * @notice Called by someone to send tokens to the destination, which should be set to the HubPool.\n * @param token Token to send to destination.\n */\n function retrieve(IERC20Upgradeable token) public nonReentrant onlyChainId(l1ChainId) {\n if (address(token) == address(l1Weth)) {\n // For WETH, there is a pre-deposit step to ensure any ETH that has been sent to the contract is captured.\n //slither-disable-next-line arbitrary-send-eth\n l1Weth.deposit{ value: address(this).balance }();\n }\n token.safeTransfer(destination, token.balanceOf(address(this)));\n }\n\n /**\n * @notice Called to initiate an l1 exit (withdrawal) of matic tokens that have been sent over the plasma bridge.\n * @param data the proof data to trigger the exit. Can be generated using the maticjs-plasma package.\n */\n function callExit(bytes memory data) public nonReentrant onlyChainId(l1ChainId) {\n PolygonERC20Predicate erc20Predicate = PolygonERC20Predicate(l1PolygonRegistry.erc20Predicate());\n erc20Predicate.startExitWithBurntTokens(data);\n }\n\n receive() external payable {\n // This method is empty to avoid any gas expendatures that might cause transfers to fail.\n // Note: the fact that there is _no_ code in this function means that matic can be erroneously transferred in\n // to the contract on the polygon side. These tokens would be locked indefinitely since the receive function\n // cannot be called on the polygon side. While this does have some downsides, the lack of any functionality\n // in this function means that it has no chance of running out of gas on transfers, which is a much more\n // important benefit. This just makes the matic token risk similar to that of ERC20s that are erroneously\n // sent to the contract.\n }\n\n function _requireChainId(uint256 chainId) internal view {\n require(block.chainid == chainId, \"Cannot run method on this chain\");\n }\n}\n" + }, + "contracts/PolygonZkEVM_SpokePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./SpokePool.sol\";\nimport \"./external/interfaces/IPolygonZkEVMBridge.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n/**\n * @notice Define interface for PolygonZkEVM Bridge message receiver\n * See https://github.com/0xPolygonHermez/zkevm-contracts/blob/53e95f3a236d8bea87c27cb8714a5d21496a3b20/contracts/interfaces/IBridgeMessageReceiver.sol\n */\ninterface IBridgeMessageReceiver {\n /**\n * @notice This will be called by the Polygon zkEVM Bridge on L2 to relay a message sent from the HubPool.\n * @param originAddress Address of the original message sender on L1.\n * @param originNetwork Polygon zkEVM's internal network id of source chain.\n * @param data Data to be received and executed on this contract.\n */\n function onMessageReceived(\n address originAddress,\n uint32 originNetwork,\n bytes memory data\n ) external payable;\n}\n\n/**\n * @notice Polygon zkEVM Spoke pool.\n * @custom:security-contact bugs@across.to\n */\ncontract PolygonZkEVM_SpokePool is SpokePool, IBridgeMessageReceiver {\n using SafeERC20 for IERC20;\n\n // Address of Polygon zkEVM's Canonical Bridge on L2.\n IPolygonZkEVMBridge public l2PolygonZkEVMBridge;\n\n // Polygon zkEVM's internal network id for L1.\n uint32 public constant POLYGON_ZKEVM_L1_NETWORK_ID = 0;\n\n // Warning: this variable should _never_ be touched outside of this contract. It is intentionally set to be\n // private. Leaving it set to true can permanently disable admin calls.\n bool private adminCallValidated;\n\n /**************************************\n * ERRORS *\n **************************************/\n error AdminCallValidatedAlreadySet();\n error CallerNotBridge();\n error OriginSenderNotCrossDomain();\n error SourceChainNotHubChain();\n error AdminCallNotValidated();\n\n /**************************************\n * EVENTS *\n **************************************/\n event SetPolygonZkEVMBridge(address indexed newPolygonZkEVMBridge, address indexed oldPolygonZkEVMBridge);\n event ReceivedMessageFromL1(address indexed caller, address indexed originAddress);\n\n // Note: validating calls this way ensures that strange calls coming from the onMessageReceived won't be\n // misinterpreted. Put differently, just checking that originAddress == crossDomainAdmint is not sufficient.\n // All calls that have admin privileges must be fired from within the onMessageReceived method that's gone\n // through validation where the sender is checked and the sender from the other chain is also validated.\n // This modifier sets the adminCallValidated variable so this condition can be checked in _requireAdminSender().\n modifier validateInternalCalls() {\n // Make sure adminCallValidated is set to True only once at beginning of onMessageReceived, which prevents\n // onMessageReceived from being re-entered.\n if (adminCallValidated) {\n revert AdminCallValidatedAlreadySet();\n }\n\n // This sets a variable indicating that we're now inside a validated call.\n // Note: this is used by other methods to ensure that this call has been validated by this method and is not\n // spoofed.\n adminCallValidated = true;\n\n _;\n\n // Reset adminCallValidated to false to disallow admin calls after this method exits.\n adminCallValidated = false;\n }\n\n /**\n * @notice Construct Polygon zkEVM specific SpokePool.\n * @param _wrappedNativeTokenAddress Address of WETH on Polygon zkEVM.\n * @param _depositQuoteTimeBuffer Quote timestamps can't be set more than this amount\n * into the past from the block time of the deposit.\n * @param _fillDeadlineBuffer Fill deadlines can't be set more than this amount\n * into the future from the block time of the deposit.\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeTokenAddress,\n uint32 _depositQuoteTimeBuffer,\n uint32 _fillDeadlineBuffer\n ) SpokePool(_wrappedNativeTokenAddress, _depositQuoteTimeBuffer, _fillDeadlineBuffer) {} // solhint-disable-line no-empty-blocks\n\n /**\n * @notice Construct the Polygon zkEVM SpokePool.\n * @param _l2PolygonZkEVMBridge Address of Polygon zkEVM's canonical bridge contract on L2.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n */\n function initialize(\n IPolygonZkEVMBridge _l2PolygonZkEVMBridge,\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool\n ) public initializer {\n __SpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool);\n _setL2PolygonZkEVMBridge(_l2PolygonZkEVMBridge);\n }\n\n /**\n * @notice Admin can reset the Polygon zkEVM bridge contract address.\n * @param _l2PolygonZkEVMBridge Address of the new canonical bridge.\n */\n function setL2PolygonZkEVMBridge(IPolygonZkEVMBridge _l2PolygonZkEVMBridge) external onlyAdmin {\n _setL2PolygonZkEVMBridge(_l2PolygonZkEVMBridge);\n }\n\n /**\n * @notice This will be called by the Polygon zkEVM Bridge on L2 to relay a message sent from the HubPool.\n * @param _originAddress Address of the original message sender on L1.\n * @param _originNetwork Polygon zkEVM's internal network id of source chain.\n * @param _data Data to be received and executed on this contract.\n */\n function onMessageReceived(\n address _originAddress,\n uint32 _originNetwork,\n bytes memory _data\n ) external payable override validateInternalCalls {\n if (msg.sender != address(l2PolygonZkEVMBridge)) {\n revert CallerNotBridge();\n }\n if (_originAddress != crossDomainAdmin) {\n revert OriginSenderNotCrossDomain();\n }\n if (_originNetwork != POLYGON_ZKEVM_L1_NETWORK_ID) {\n revert SourceChainNotHubChain();\n }\n\n /// @custom:oz-upgrades-unsafe-allow delegatecall\n (bool success, ) = address(this).delegatecall(_data);\n require(success, \"delegatecall failed\");\n\n emit ReceivedMessageFromL1(msg.sender, _originAddress);\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n /**\n * @notice Wraps any ETH into WETH before executing base function. This is necessary because SpokePool receives\n * ETH over the canonical token bridge instead of WETH.\n */\n function _preExecuteLeafHook(address l2TokenAddress) internal override {\n if (l2TokenAddress == address(wrappedNativeToken)) _depositEthToWeth();\n }\n\n // Wrap any ETH owned by this contract so we can send expected L2 token to recipient. This is necessary because\n // this SpokePool will receive ETH from the canonical token bridge instead of WETH. This may not be neccessary\n // if ETH on Polygon zkEVM is treated as ETH and the fallback() function is triggered when this contract receives\n // ETH. We will have to test this but this function for now allows the contract to safely convert all of its\n // held ETH into WETH at the cost of higher gas costs.\n function _depositEthToWeth() internal {\n //slither-disable-next-line arbitrary-send-eth\n if (address(this).balance > 0) wrappedNativeToken.deposit{ value: address(this).balance }();\n }\n\n function _bridgeTokensToHubPool(uint256 amountToReturn, address l2TokenAddress) internal override {\n // SpokePool is expected to receive ETH from the L1 HubPool, then we need to first unwrap it to ETH and then\n // send ETH directly via the native L2 bridge.\n if (l2TokenAddress == address(wrappedNativeToken)) {\n WETH9Interface(l2TokenAddress).withdraw(amountToReturn); // Unwrap into ETH.\n l2PolygonZkEVMBridge.bridgeAsset{ value: amountToReturn }(\n POLYGON_ZKEVM_L1_NETWORK_ID,\n hubPool,\n amountToReturn,\n address(0),\n true, // Indicates if the new global exit root is updated or not, which is true for asset bridges\n \"\"\n );\n } else {\n IERC20(l2TokenAddress).safeIncreaseAllowance(address(l2PolygonZkEVMBridge), amountToReturn);\n l2PolygonZkEVMBridge.bridgeAsset(\n POLYGON_ZKEVM_L1_NETWORK_ID,\n hubPool,\n amountToReturn,\n l2TokenAddress,\n true, // Indicates if the new global exit root is updated or not, which is true for asset bridges\n \"\"\n );\n }\n }\n\n // Check that the onMessageReceived method has validated the method to ensure the sender is authenticated.\n function _requireAdminSender() internal view override {\n if (!adminCallValidated) {\n revert AdminCallNotValidated();\n }\n }\n\n function _setL2PolygonZkEVMBridge(IPolygonZkEVMBridge _newL2PolygonZkEVMBridge) internal {\n address oldL2PolygonZkEVMBridge = address(l2PolygonZkEVMBridge);\n l2PolygonZkEVMBridge = _newL2PolygonZkEVMBridge;\n emit SetPolygonZkEVMBridge(address(_newL2PolygonZkEVMBridge), oldL2PolygonZkEVMBridge);\n }\n}\n" + }, + "contracts/Scroll_SpokePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./SpokePool.sol\";\nimport \"@scroll-tech/contracts/L2/gateways/IL2GatewayRouter.sol\";\nimport \"@scroll-tech/contracts/libraries/IScrollMessenger.sol\";\n\ninterface IL2GatewayRouterExtended is IL2GatewayRouter {\n function defaultERC20Gateway() external view returns (address);\n\n function getERC20Gateway(address) external view returns (address);\n}\n\n/**\n * @title Scroll_SpokePool\n * @notice Modified SpokePool contract deployed on Scroll to facilitate token transfers\n * from Scroll to the HubPool\n * @custom:security-contact bugs@across.to\n */\ncontract Scroll_SpokePool is SpokePool {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice The address of the official l2GatewayRouter contract for Scroll for bridging tokens from L2 -> L1\n * @dev We can find these (main/test)net deployments here: https://docs.scroll.io/en/developers/scroll-contracts/#scroll-contracts\n */\n IL2GatewayRouterExtended public l2GatewayRouter;\n\n /**\n * @notice The address of the official messenger contract for Scroll from L2 -> L1\n * @dev We can find these (main/test)net deployments here: https://docs.scroll.io/en/developers/scroll-contracts/#scroll-contracts\n */\n IScrollMessenger public l2ScrollMessenger;\n\n /**************************************\n * EVENTS *\n **************************************/\n\n event SetL2GatewayRouter(address indexed newGatewayRouter, address oldGatewayRouter);\n event SetL2ScrollMessenger(address indexed newScrollMessenger, address oldScrollMessenger);\n\n /**************************************\n * PUBLIC FUNCTIONS *\n **************************************/\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeTokenAddress,\n uint32 _depositQuoteTimeBuffer,\n uint32 _fillDeadlineBuffer\n ) SpokePool(_wrappedNativeTokenAddress, _depositQuoteTimeBuffer, _fillDeadlineBuffer) {} // solhint-disable-line no-empty-blocks\n\n /**\n * @notice Construct the Scroll SpokePool.\n * @param _l2GatewayRouter Standard bridge contract.\n * @param _l2ScrollMessenger Scroll Messenger contract on L2.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n */\n function initialize(\n IL2GatewayRouterExtended _l2GatewayRouter,\n IScrollMessenger _l2ScrollMessenger,\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool\n ) public initializer {\n __SpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool);\n _setL2GatewayRouter(_l2GatewayRouter);\n _setL2MessageService(_l2ScrollMessenger);\n }\n\n /**\n * @notice Change the L2 Gateway Router. Changed only by admin.\n * @param _l2GatewayRouter New address of L2 gateway router.\n */\n function setL2GatewayRouter(IL2GatewayRouterExtended _l2GatewayRouter) public onlyAdmin nonReentrant {\n _setL2GatewayRouter(_l2GatewayRouter);\n }\n\n /**\n * @notice Change L2 message service address. Callable only by admin.\n * @param _l2ScrollMessenger New address of L2 messenger.\n */\n function setL2ScrollMessenger(IScrollMessenger _l2ScrollMessenger) public onlyAdmin nonReentrant {\n _setL2MessageService(_l2ScrollMessenger);\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n /**\n * @notice Bridge tokens to the HubPool.\n * @param amountToReturn Amount of tokens to bridge to the HubPool.\n * @param l2TokenAddress Address of the token to bridge.\n */\n function _bridgeTokensToHubPool(uint256 amountToReturn, address l2TokenAddress) internal virtual override {\n // Tokens with a custom ERC20 gateway require an approval in order to withdraw.\n address erc20Gateway = l2GatewayRouter.getERC20Gateway(l2TokenAddress);\n if (erc20Gateway != l2GatewayRouter.defaultERC20Gateway()) {\n IERC20Upgradeable(l2TokenAddress).safeIncreaseAllowance(erc20Gateway, amountToReturn);\n }\n\n // The scroll bridge handles arbitrary ERC20 tokens and is mindful of the official WETH address on-chain.\n // We don't need to do anything specific to differentiate between WETH and a separate ERC20.\n // Note: This happens due to the L2GatewayRouter.getERC20Gateway() call\n l2GatewayRouter.withdrawERC20(\n l2TokenAddress,\n hubPool,\n amountToReturn,\n // This is the gasLimit for the L2 -> L1 transaction. We don't need to set it.\n // Scroll official docs say it's for compatibility reasons.\n // See: https://github.com/scroll-tech/scroll/blob/0a8164ee5b63ed5d3bd5e7b39d91445a3176e142/contracts/src/L2/gateways/IL2ERC20Gateway.sol#L69-L80\n 0\n );\n }\n\n /**\n * @notice Verifies that calling method is from the cross domain admin.\n */\n function _requireAdminSender() internal view override {\n // The xdomainMessageSender is set within the Scroll messenger right\n // before the call to this function (and reset afterwards). This represents\n // the address that sent the message from L1 to L2. If the calling contract\n // isn't the Scroll messenger, then the xdomainMessageSender will be the zero\n // address and *NOT* cross domain admin.\n address _xDomainSender = l2ScrollMessenger.xDomainMessageSender();\n require(_xDomainSender == crossDomainAdmin, \"Sender must be admin\");\n }\n\n function _setL2GatewayRouter(IL2GatewayRouterExtended _l2GatewayRouter) internal {\n address oldL2GatewayRouter = address(l2GatewayRouter);\n l2GatewayRouter = _l2GatewayRouter;\n emit SetL2GatewayRouter(address(_l2GatewayRouter), oldL2GatewayRouter);\n }\n\n function _setL2MessageService(IScrollMessenger _l2ScrollMessenger) internal {\n address oldL2ScrollMessenger = address(l2ScrollMessenger);\n l2ScrollMessenger = _l2ScrollMessenger;\n emit SetL2ScrollMessenger(address(_l2ScrollMessenger), oldL2ScrollMessenger);\n }\n}\n" + }, + "contracts/SpokePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./MerkleLib.sol\";\nimport \"./external/interfaces/WETH9Interface.sol\";\nimport \"./interfaces/SpokePoolMessageHandler.sol\";\nimport \"./interfaces/SpokePoolInterface.sol\";\nimport \"./interfaces/V3SpokePoolInterface.sol\";\nimport \"./upgradeable/MultiCallerUpgradeable.sol\";\nimport \"./upgradeable/EIP712CrossChainUpgradeable.sol\";\nimport \"./upgradeable/AddressLibUpgradeable.sol\";\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts/utils/math/SignedMath.sol\";\n\n/**\n * @title SpokePool\n * @notice Base contract deployed on source and destination chains enabling depositors to transfer assets from source to\n * destination. Deposit orders are fulfilled by off-chain relayers who also interact with this contract. Deposited\n * tokens are locked on the source chain and relayers send the recipient the desired token currency and amount\n * on the destination chain. Locked source chain tokens are later sent over the canonical token bridge to L1 HubPool.\n * Relayers are refunded with destination tokens out of this contract after another off-chain actor, a \"data worker\",\n * submits a proof that the relayer correctly submitted a relay on this SpokePool.\n * @custom:security-contact bugs@across.to\n */\nabstract contract SpokePool is\n V3SpokePoolInterface,\n SpokePoolInterface,\n UUPSUpgradeable,\n ReentrancyGuardUpgradeable,\n MultiCallerUpgradeable,\n EIP712CrossChainUpgradeable\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using AddressLibUpgradeable for address;\n\n // Address of the L1 contract that acts as the owner of this SpokePool. This should normally be set to the HubPool\n // address. The crossDomainAdmin address is unused when the SpokePool is deployed to the same chain as the HubPool.\n address public crossDomainAdmin;\n\n // Address of the L1 contract that will send tokens to and receive tokens from this contract to fund relayer\n // refunds and slow relays.\n address public hubPool;\n\n // Note: The following two storage variables prefixed with DEPRECATED used to be variables that could be set by\n // the cross-domain admin. Admins ended up not changing these in production, so to reduce\n // gas in deposit/fill functions, we are converting them to private variables to maintain the contract\n // storage layout and replacing them with immutable or constant variables, because retrieving a constant\n // value is cheaper than retrieving a storage variable. Please see out the immutable/constant variable section.\n WETH9Interface private DEPRECATED_wrappedNativeToken;\n uint32 private DEPRECATED_depositQuoteTimeBuffer;\n\n // Count of deposits is used to construct a unique deposit identifier for this spoke pool.\n uint32 public numberOfDeposits;\n\n // Whether deposits and fills are disabled.\n bool public pausedFills;\n bool public pausedDeposits;\n\n // This contract can store as many root bundles as the HubPool chooses to publish here.\n RootBundle[] public rootBundles;\n\n // Origin token to destination token routings can be turned on or off, which can enable or disable deposits.\n mapping(address => mapping(uint256 => bool)) public enabledDepositRoutes;\n\n // Each relay is associated with the hash of parameters that uniquely identify the original deposit and a relay\n // attempt for that deposit. The relay itself is just represented as the amount filled so far. The total amount to\n // relay, the fees, and the agents are all parameters included in the hash key.\n mapping(bytes32 => uint256) private DEPRECATED_relayFills;\n\n // Note: We will likely un-deprecate the fill and deposit counters to implement a better\n // dynamic LP fee mechanism but for now we'll deprecate it to reduce bytecode\n // in deposit/fill functions. These counters are designed to implement a fee mechanism that is based on a\n // canonical history of deposit and fill events and how they update a virtual running balance of liabilities and\n // assets, which then determines the LP fee charged to relays.\n\n // This keeps track of the worst-case liabilities due to fills.\n // It is never reset. Users should only rely on it to determine the worst-case increase in liabilities between\n // two points. This is used to provide frontrunning protection to ensure the relayer's assumptions about the state\n // upon which their expected repayments are based will not change before their transaction is mined.\n mapping(address => uint256) private DEPRECATED_fillCounter;\n\n // This keeps track of the total running deposits for each token. This allows depositors to protect themselves from\n // frontrunning that might change their worst-case quote.\n mapping(address => uint256) private DEPRECATED_depositCounter;\n\n // This tracks the number of identical refunds that have been requested.\n // The intention is to allow an off-chain system to know when this could be a duplicate and ensure that the other\n // requests are known and accounted for.\n mapping(bytes32 => uint256) private DEPRECATED_refundsRequested;\n\n // Mapping of V3 relay hashes to fill statuses. Distinguished from relayFills\n // to eliminate any chance of collision between pre and post V3 relay hashes.\n mapping(bytes32 => uint256) public fillStatuses;\n\n /**************************************************************\n * CONSTANT/IMMUTABLE VARIABLES *\n **************************************************************/\n // Constant and immutable variables do not take up storage slots and are instead added to the contract bytecode\n // at compile time. The difference between them is that constant variables must be declared inline, meaning\n // that they cannot be changed in production without changing the contract code, while immutable variables\n // can be set in the constructor. Therefore we use the immutable keyword for variables that we might want to be\n // different for each child contract (one obvious example of this is the wrappedNativeToken) or that we might\n // want to update in the future like depositQuoteTimeBuffer. Constants are unlikely to ever be changed.\n\n // Address of wrappedNativeToken contract for this network. If an origin token matches this, then the caller can\n // optionally instruct this contract to wrap native tokens when depositing (ie ETH->WETH or MATIC->WMATIC).\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n WETH9Interface public immutable wrappedNativeToken;\n\n // Any deposit quote times greater than or less than this value to the current contract time is blocked. Forces\n // caller to use an approximately \"current\" realized fee.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint32 public immutable depositQuoteTimeBuffer;\n\n // The fill deadline can only be set this far into the future from the timestamp of the deposit on this contract.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint32 public immutable fillDeadlineBuffer;\n\n uint256 public constant MAX_TRANSFER_SIZE = 1e36;\n\n bytes32 public constant UPDATE_V3_DEPOSIT_DETAILS_HASH =\n keccak256(\n \"UpdateDepositDetails(uint32 depositId,uint256 originChainId,uint256 updatedOutputAmount,address updatedRecipient,bytes updatedMessage)\"\n );\n\n // Default chain Id used to signify that no repayment is requested, for example when executing a slow fill.\n uint256 public constant EMPTY_REPAYMENT_CHAIN_ID = 0;\n // Default address used to signify that no relayer should be credited with a refund, for example\n // when executing a slow fill.\n address public constant EMPTY_RELAYER = address(0);\n // This is the magic value that signals to the off-chain validator\n // that this deposit can never expire. A deposit with this fill deadline should always be eligible for a\n // slow fill, meaning that its output token and input token must be \"equivalent\". Therefore, this value is only\n // used as a fillDeadline in deposit(), a soon to be deprecated function that also hardcodes outputToken to\n // the zero address, which forces the off-chain validator to replace the output token with the equivalent\n // token for the input token. By using this magic value, off-chain validators do not have to keep\n // this event in their lookback window when querying for expired deposts.\n uint32 public constant INFINITE_FILL_DEADLINE = type(uint32).max;\n /****************************************\n * EVENTS *\n ****************************************/\n event SetXDomainAdmin(address indexed newAdmin);\n event SetHubPool(address indexed newHubPool);\n event EnabledDepositRoute(address indexed originToken, uint256 indexed destinationChainId, bool enabled);\n event RelayedRootBundle(\n uint32 indexed rootBundleId,\n bytes32 indexed relayerRefundRoot,\n bytes32 indexed slowRelayRoot\n );\n event ExecutedRelayerRefundRoot(\n uint256 amountToReturn,\n uint256 indexed chainId,\n uint256[] refundAmounts,\n uint32 indexed rootBundleId,\n uint32 indexed leafId,\n address l2TokenAddress,\n address[] refundAddresses,\n address caller\n );\n event TokensBridged(\n uint256 amountToReturn,\n uint256 indexed chainId,\n uint32 indexed leafId,\n address indexed l2TokenAddress,\n address caller\n );\n event EmergencyDeleteRootBundle(uint256 indexed rootBundleId);\n event PausedDeposits(bool isPaused);\n event PausedFills(bool isPaused);\n\n /// EVENTS BELOW ARE DEPRECATED AND EXIST FOR BACKWARDS COMPATIBILITY ONLY.\n /// @custom:audit FOLLOWING EVENT TO BE DEPRECATED\n event FundsDeposited(\n uint256 amount,\n uint256 originChainId,\n uint256 indexed destinationChainId,\n int64 relayerFeePct,\n uint32 indexed depositId,\n uint32 quoteTimestamp,\n address originToken,\n address recipient,\n address indexed depositor,\n bytes message\n );\n /// @custom:audit FOLLOWING EVENT TO BE DEPRECATED\n event RequestedSpeedUpDeposit(\n int64 newRelayerFeePct,\n uint32 indexed depositId,\n address indexed depositor,\n address updatedRecipient,\n bytes updatedMessage,\n bytes depositorSignature\n );\n /// @custom:audit FOLLOWING EVENT TO BE DEPRECATED\n event FilledRelay(\n uint256 amount,\n uint256 totalFilledAmount,\n uint256 fillAmount,\n uint256 repaymentChainId,\n uint256 indexed originChainId,\n uint256 destinationChainId,\n int64 relayerFeePct,\n int64 realizedLpFeePct,\n uint32 indexed depositId,\n address destinationToken,\n address relayer,\n address indexed depositor,\n address recipient,\n bytes message,\n RelayExecutionInfo updatableRelayData\n );\n /**\n * @notice Packs together information to include in FilledRelay event.\n * @dev This struct is emitted as opposed to its constituent parameters due to the limit on number of\n * parameters in an event.\n * @param recipient Recipient of the relayed funds.\n * @param message Message included in the relay.\n * @param relayerFeePct Relayer fee pct used for this relay.\n * @param isSlowRelay Whether this is a slow relay.\n * @param payoutAdjustmentPct Adjustment to the payout amount.\n */\n /// @custom:audit FOLLOWING STRUCT TO BE DEPRECATED\n struct RelayExecutionInfo {\n address recipient;\n bytes message;\n int64 relayerFeePct;\n bool isSlowRelay;\n int256 payoutAdjustmentPct;\n }\n\n /// EVENTS ABOVE ARE DEPRECATED AND EXIST FOR BACKWARDS COMPATIBILITY ONLY.\n\n /**\n * @notice Construct the SpokePool. Normally, logic contracts used in upgradeable proxies shouldn't\n * have constructors since the following code will be executed within the logic contract's state, not the\n * proxy contract's state. However, if we restrict the constructor to setting only immutable variables, then\n * we are safe because immutable variables are included in the logic contract's bytecode rather than its storage.\n * @dev Do not leave an implementation contract uninitialized. An uninitialized implementation contract can be\n * taken over by an attacker, which may impact the proxy. To prevent the implementation contract from being\n * used, you should invoke the _disableInitializers function in the constructor to automatically lock it when\n * it is deployed:\n * @param _wrappedNativeTokenAddress wrappedNativeToken address for this network to set.\n * @param _depositQuoteTimeBuffer depositQuoteTimeBuffer to set. Quote timestamps can't be set more than this amount\n * into the past from the block time of the deposit.\n * @param _fillDeadlineBuffer fillDeadlineBuffer to set. Fill deadlines can't be set more than this amount\n * into the future from the block time of the deposit.\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeTokenAddress,\n uint32 _depositQuoteTimeBuffer,\n uint32 _fillDeadlineBuffer\n ) {\n wrappedNativeToken = WETH9Interface(_wrappedNativeTokenAddress);\n depositQuoteTimeBuffer = _depositQuoteTimeBuffer;\n fillDeadlineBuffer = _fillDeadlineBuffer;\n _disableInitializers();\n }\n\n /**\n * @notice Construct the base SpokePool.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n */\n function __SpokePool_init(\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool\n ) public onlyInitializing {\n numberOfDeposits = _initialDepositId;\n __EIP712_init(\"ACROSS-V2\", \"1.0.0\");\n __UUPSUpgradeable_init();\n __ReentrancyGuard_init();\n _setCrossDomainAdmin(_crossDomainAdmin);\n _setHubPool(_hubPool);\n }\n\n /****************************************\n * MODIFIERS *\n ****************************************/\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n * @dev This should be set to cross domain admin for specific SpokePool.\n */\n modifier onlyAdmin() {\n _requireAdminSender();\n _;\n }\n\n modifier unpausedDeposits() {\n if (pausedDeposits) revert DepositsArePaused();\n _;\n }\n\n modifier unpausedFills() {\n if (pausedFills) revert FillsArePaused();\n _;\n }\n\n /**************************************\n * ADMIN FUNCTIONS *\n **************************************/\n\n // Allows cross domain admin to upgrade UUPS proxy implementation.\n function _authorizeUpgrade(address newImplementation) internal override onlyAdmin {}\n\n /**\n * @notice Pauses deposit-related functions. This is intended to be used if this contract is deprecated or when\n * something goes awry.\n * @dev Affects `deposit()` but not `speedUpDeposit()`, so that existing deposits can be sped up and still\n * relayed.\n * @param pause true if the call is meant to pause the system, false if the call is meant to unpause it.\n */\n function pauseDeposits(bool pause) public override onlyAdmin nonReentrant {\n pausedDeposits = pause;\n emit PausedDeposits(pause);\n }\n\n /**\n * @notice Pauses fill-related functions. This is intended to be used if this contract is deprecated or when\n * something goes awry.\n * @dev Affects fillRelayWithUpdatedDeposit() and fillRelay().\n * @param pause true if the call is meant to pause the system, false if the call is meant to unpause it.\n */\n function pauseFills(bool pause) public override onlyAdmin nonReentrant {\n pausedFills = pause;\n emit PausedFills(pause);\n }\n\n /**\n * @notice Change cross domain admin address. Callable by admin only.\n * @param newCrossDomainAdmin New cross domain admin.\n */\n function setCrossDomainAdmin(address newCrossDomainAdmin) public override onlyAdmin nonReentrant {\n _setCrossDomainAdmin(newCrossDomainAdmin);\n }\n\n /**\n * @notice Change L1 hub pool address. Callable by admin only.\n * @param newHubPool New hub pool.\n */\n function setHubPool(address newHubPool) public override onlyAdmin nonReentrant {\n _setHubPool(newHubPool);\n }\n\n /**\n * @notice Enable/Disable an origin token => destination chain ID route for deposits. Callable by admin only.\n * @param originToken Token that depositor can deposit to this contract.\n * @param destinationChainId Chain ID for where depositor wants to receive funds.\n * @param enabled True to enable deposits, False otherwise.\n */\n function setEnableRoute(\n address originToken,\n uint256 destinationChainId,\n bool enabled\n ) public override onlyAdmin nonReentrant {\n enabledDepositRoutes[originToken][destinationChainId] = enabled;\n emit EnabledDepositRoute(originToken, destinationChainId, enabled);\n }\n\n /**\n * @notice This method stores a new root bundle in this contract that can be executed to refund relayers, fulfill\n * slow relays, and send funds back to the HubPool on L1. This method can only be called by the admin and is\n * designed to be called as part of a cross-chain message from the HubPool's executeRootBundle method.\n * @param relayerRefundRoot Merkle root containing relayer refund leaves that can be individually executed via\n * executeRelayerRefundLeaf().\n * @param slowRelayRoot Merkle root containing slow relay fulfillment leaves that can be individually executed via\n * executeSlowRelayLeaf().\n */\n function relayRootBundle(bytes32 relayerRefundRoot, bytes32 slowRelayRoot) public override onlyAdmin nonReentrant {\n uint32 rootBundleId = uint32(rootBundles.length);\n RootBundle storage rootBundle = rootBundles.push();\n rootBundle.relayerRefundRoot = relayerRefundRoot;\n rootBundle.slowRelayRoot = slowRelayRoot;\n emit RelayedRootBundle(rootBundleId, relayerRefundRoot, slowRelayRoot);\n }\n\n /**\n * @notice This method is intended to only be used in emergencies where a bad root bundle has reached the\n * SpokePool.\n * @param rootBundleId Index of the root bundle that needs to be deleted. Note: this is intentionally a uint256\n * to ensure that a small input range doesn't limit which indices this method is able to reach.\n */\n function emergencyDeleteRootBundle(uint256 rootBundleId) public override onlyAdmin nonReentrant {\n // Deleting a struct containing a mapping does not delete the mapping in Solidity, therefore the bitmap's\n // data will still remain potentially leading to vulnerabilities down the line. The way around this would\n // be to iterate through every key in the mapping and resetting the value to 0, but this seems expensive and\n // would require a new list in storage to keep track of keys.\n //slither-disable-next-line mapping-deletion\n delete rootBundles[rootBundleId];\n emit EmergencyDeleteRootBundle(rootBundleId);\n }\n\n /**************************************\n * LEGACY DEPOSITOR FUNCTIONS *\n **************************************/\n\n /**\n * @notice Called by user to bridge funds from origin to destination chain. Depositor will effectively lock\n * tokens in this contract and receive a destination token on the destination chain. The origin => destination\n * token mapping is stored on the L1 HubPool.\n * @notice The caller must first approve this contract to spend amount of originToken.\n * @notice The originToken => destinationChainId must be enabled.\n * @notice This method is payable because the caller is able to deposit native token if the originToken is\n * wrappedNativeToken and this function will handle wrapping the native token to wrappedNativeToken.\n * @dev Produces a V3FundsDeposited event with an infinite expiry, meaning that this deposit can never expire.\n * Moreover, the event's outputToken is set to 0x0 meaning that this deposit can always be slow filled.\n * @param recipient Address to receive funds at on destination chain.\n * @param originToken Token to lock into this contract to initiate deposit.\n * @param amount Amount of tokens to deposit. Will be amount of tokens to receive less fees.\n * @param destinationChainId Denotes network where user will receive funds from SpokePool by a relayer.\n * @param relayerFeePct % of deposit amount taken out to incentivize a fast relayer.\n * @param quoteTimestamp Timestamp used by relayers to compute this deposit's realizedLPFeePct which is paid\n * to LP pool on HubPool.\n * @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\n * Note: this is intended to be used to pass along instructions for how a contract should use or allocate the tokens.\n */\n function deposit(\n address recipient,\n address originToken,\n uint256 amount,\n uint256 destinationChainId,\n int64 relayerFeePct,\n uint32 quoteTimestamp,\n bytes memory message,\n uint256 // maxCount. Deprecated.\n ) public payable override nonReentrant unpausedDeposits {\n _deposit(\n msg.sender,\n recipient,\n originToken,\n amount,\n destinationChainId,\n relayerFeePct,\n quoteTimestamp,\n message\n );\n }\n\n /**\n * @notice The only difference between depositFor and deposit is that the depositor address stored\n * in the relay hash can be overridden by the caller. This means that the passed in depositor\n * can speed up the deposit, which is useful if the deposit is taken from the end user to a middle layer\n * contract, like an aggregator or the SpokePoolVerifier, before calling deposit on this contract.\n * @notice The caller must first approve this contract to spend amount of originToken.\n * @notice The originToken => destinationChainId must be enabled.\n * @notice This method is payable because the caller is able to deposit native token if the originToken is\n * wrappedNativeToken and this function will handle wrapping the native token to wrappedNativeToken.\n * @param depositor Address who is credited for depositing funds on origin chain and can speed up the deposit.\n * @param recipient Address to receive funds at on destination chain.\n * @param originToken Token to lock into this contract to initiate deposit.\n * @param amount Amount of tokens to deposit. Will be amount of tokens to receive less fees.\n * @param destinationChainId Denotes network where user will receive funds from SpokePool by a relayer.\n * @param relayerFeePct % of deposit amount taken out to incentivize a fast relayer.\n * @param quoteTimestamp Timestamp used by relayers to compute this deposit's realizedLPFeePct which is paid\n * to LP pool on HubPool.\n * @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\n * Note: this is intended to be used to pass along instructions for how a contract should use or allocate the tokens.\n */\n function depositFor(\n address depositor,\n address recipient,\n address originToken,\n uint256 amount,\n uint256 destinationChainId,\n int64 relayerFeePct,\n uint32 quoteTimestamp,\n bytes memory message,\n uint256 // maxCount. Deprecated.\n ) public payable nonReentrant unpausedDeposits {\n _deposit(depositor, recipient, originToken, amount, destinationChainId, relayerFeePct, quoteTimestamp, message);\n }\n\n /********************************************\n * DEPOSITOR FUNCTIONS *\n ********************************************/\n\n /**\n * @notice Request to bridge input token cross chain to a destination chain and receive a specified amount\n * of output tokens. The fee paid to relayers and the system should be captured in the spread between output\n * amount and input amount when adjusted to be denominated in the input token. A relayer on the destination\n * chain will send outputAmount of outputTokens to the recipient and receive inputTokens on a repayment\n * chain of their choice. Therefore, the fee should account for destination fee transaction costs,\n * the relayer's opportunity cost of capital while they wait to be refunded following an optimistic challenge\n * window in the HubPool, and the system fee that they'll be charged.\n * @dev On the destination chain, the hash of the deposit data will be used to uniquely identify this deposit, so\n * modifying any params in it will result in a different hash and a different deposit. The hash will comprise\n * all parameters to this function along with this chain's chainId(). Relayers are only refunded for filling\n * deposits with deposit hashes that map exactly to the one emitted by this contract.\n * @param depositor The account credited with the deposit who can request to \"speed up\" this deposit by modifying\n * the output amount, recipient, and message.\n * @param recipient The account receiving funds on the destination chain. Can be an EOA or a contract. If\n * the output token is the wrapped native token for the chain, then the recipient will receive native token if\n * an EOA or wrapped native token if a contract.\n * @param inputToken The token pulled from the caller's account and locked into this contract to\n * initiate the deposit. The equivalent of this token on the relayer's repayment chain of choice will be sent\n * as a refund. If this is equal to the wrapped native token then the caller can optionally pass in native token as\n * msg.value, as long as msg.value = inputTokenAmount.\n * @param outputToken The token that the relayer will send to the recipient on the destination chain. Must be an\n * ERC20.\n * @param inputAmount The amount of input tokens to pull from the caller's account and lock into this contract.\n * This amount will be sent to the relayer on their repayment chain of choice as a refund following an optimistic\n * challenge window in the HubPool, less a system fee.\n * @param outputAmount The amount of output tokens that the relayer will send to the recipient on the destination.\n * @param destinationChainId The destination chain identifier. Must be enabled along with the input token\n * as a valid deposit route from this spoke pool or this transaction will revert.\n * @param exclusiveRelayer The relayer that will be exclusively allowed to fill this deposit before the\n * exclusivity deadline timestamp. This must be a valid, non-zero address if the exclusivity deadline is\n * greater than the current block.timestamp. If the exclusivity deadline is < currentTime, then this must be\n * address(0), and vice versa if this is address(0).\n * @param quoteTimestamp The HubPool timestamp that is used to determine the system fee paid by the depositor.\n * This must be set to some time between [currentTime - depositQuoteTimeBuffer, currentTime]\n * where currentTime is block.timestamp on this chain or this transaction will revert.\n * @param fillDeadline The deadline for the relayer to fill the deposit. After this destination chain timestamp,\n * the fill will revert on the destination chain. Must be set between [currentTime, currentTime + fillDeadlineBuffer]\n * where currentTime is block.timestamp on this chain or this transaction will revert.\n * @param exclusivityDeadline The deadline for the exclusive relayer to fill the deposit. After this\n * destination chain timestamp, anyone can fill this deposit on the destination chain. If exclusiveRelayer is set\n * to address(0), then this also must be set to 0, (and vice versa), otherwise this must be set >= current time.\n * @param message The message to send to the recipient on the destination chain if the recipient is a contract.\n * If the message is not empty, the recipient contract must implement handleV3AcrossMessage() or the fill will revert.\n */\n function depositV3(\n address depositor,\n address recipient,\n address inputToken,\n address outputToken,\n uint256 inputAmount,\n uint256 outputAmount,\n uint256 destinationChainId,\n address exclusiveRelayer,\n uint32 quoteTimestamp,\n uint32 fillDeadline,\n uint32 exclusivityDeadline,\n bytes calldata message\n ) public payable override nonReentrant unpausedDeposits {\n // Check that deposit route is enabled for the input token. There are no checks required for the output token\n // which is pulled from the relayer at fill time and passed through this contract atomically to the recipient.\n if (!enabledDepositRoutes[inputToken][destinationChainId]) revert DisabledRoute();\n\n // Require that quoteTimestamp has a maximum age so that depositors pay an LP fee based on recent HubPool usage.\n // It is assumed that cross-chain timestamps are normally loosely in-sync, but clock drift can occur. If the\n // SpokePool time stalls or lags significantly, it is still possible to make deposits by setting quoteTimestamp\n // within the configured buffer. The owner should pause deposits/fills if this is undesirable.\n // This will underflow if quoteTimestamp is more than depositQuoteTimeBuffer;\n // this is safe but will throw an unintuitive error.\n\n // slither-disable-next-line timestamp\n uint256 currentTime = getCurrentTime();\n if (currentTime - quoteTimestamp > depositQuoteTimeBuffer) revert InvalidQuoteTimestamp();\n\n // fillDeadline is relative to the destination chain.\n // Don’t allow fillDeadline to be more than several bundles into the future.\n // This limits the maximum required lookback for dataworker and relayer instances.\n // Also, don't allow fillDeadline to be in the past. This poses a potential UX issue if the destination\n // chain time keeping and this chain's time keeping are out of sync but is not really a practical hurdle\n // unless they are significantly out of sync or the depositor is setting very short fill deadlines. This latter\n // situation won't be a problem for honest users.\n if (fillDeadline < currentTime || fillDeadline > currentTime + fillDeadlineBuffer) revert InvalidFillDeadline();\n\n // As a safety measure, prevent caller from inadvertently locking funds during exclusivity period\n // by forcing them to specify an exclusive relayer if the exclusivity period\n // is in the future. If this deadline is 0, then the exclusive relayer must also be address(0).\n // @dev Checks if either are > 0 by bitwise or-ing.\n if (uint256(uint160(exclusiveRelayer)) | exclusivityDeadline != 0) {\n // Now that we know one is nonzero, we need to perform checks on each.\n // Check that exclusive relayer is nonzero.\n if (exclusiveRelayer == address(0)) revert InvalidExclusiveRelayer();\n\n // Check that deadline is in the future.\n if (exclusivityDeadline < currentTime) revert InvalidExclusivityDeadline();\n }\n\n // No need to sanity check exclusivityDeadline because if its bigger than fillDeadline, then\n // there the full deadline is exclusive, and if its too small, then there is no exclusivity period.\n\n // If the address of the origin token is a wrappedNativeToken contract and there is a msg.value with the\n // transaction then the user is sending the native token. In this case, the native token should be\n // wrapped.\n if (inputToken == address(wrappedNativeToken) && msg.value > 0) {\n if (msg.value != inputAmount) revert MsgValueDoesNotMatchInputAmount();\n wrappedNativeToken.deposit{ value: msg.value }();\n // Else, it is a normal ERC20. In this case pull the token from the caller as per normal.\n // Note: this includes the case where the L2 caller has WETH (already wrapped ETH) and wants to bridge them.\n // In this case the msg.value will be set to 0, indicating a \"normal\" ERC20 bridging action.\n } else {\n // msg.value should be 0 if input token isn't the wrapped native token.\n if (msg.value != 0) revert MsgValueDoesNotMatchInputAmount();\n IERC20Upgradeable(inputToken).safeTransferFrom(msg.sender, address(this), inputAmount);\n }\n\n emit V3FundsDeposited(\n inputToken,\n outputToken,\n inputAmount,\n outputAmount,\n destinationChainId,\n // Increment count of deposits so that deposit ID for this spoke pool is unique.\n numberOfDeposits++,\n quoteTimestamp,\n fillDeadline,\n exclusivityDeadline,\n depositor,\n recipient,\n exclusiveRelayer,\n message\n );\n }\n\n /**\n * @notice Submits deposit and sets quoteTimestamp to current Time. Sets fill and exclusivity\n * deadlines as offsets added to the current time. This function is designed to be called by users\n * such as Multisig contracts who do not have certainty when their transaction will mine.\n * @param depositor The account credited with the deposit who can request to \"speed up\" this deposit by modifying\n * the output amount, recipient, and message.\n * @param recipient The account receiving funds on the destination chain. Can be an EOA or a contract. If\n * the output token is the wrapped native token for the chain, then the recipient will receive native token if\n * an EOA or wrapped native token if a contract.\n * @param inputToken The token pulled from the caller's account and locked into this contract to\n * initiate the deposit. The equivalent of this token on the relayer's repayment chain of choice will be sent\n * as a refund. If this is equal to the wrapped native token then the caller can optionally pass in native token as\n * msg.value, as long as msg.value = inputTokenAmount.\n * @param outputToken The token that the relayer will send to the recipient on the destination chain. Must be an\n * ERC20.\n * @param inputAmount The amount of input tokens to pull from the caller's account and lock into this contract.\n * This amount will be sent to the relayer on their repayment chain of choice as a refund following an optimistic\n * challenge window in the HubPool, plus a system fee.\n * @param outputAmount The amount of output tokens that the relayer will send to the recipient on the destination.\n * @param destinationChainId The destination chain identifier. Must be enabled along with the input token\n * as a valid deposit route from this spoke pool or this transaction will revert.\n * @param exclusiveRelayer The relayer that will be exclusively allowed to fill this deposit before the\n * exclusivity deadline timestamp.\n * @param fillDeadlineOffset Added to the current time to set the fill deadline, which is the deadline for the\n * relayer to fill the deposit. After this destination chain timestamp, the fill will revert on the\n * destination chain.\n * @param exclusivityDeadline The latest timestamp that only the exclusive relayer can fill the deposit. After this\n * destination chain timestamp, anyone can fill this deposit on the destination chain. Should be 0 if\n * exclusive relayer is 0.\n * @param message The message to send to the recipient on the destination chain if the recipient is a contract.\n * If the message is not empty, the recipient contract must implement handleV3AcrossMessage() or the fill will revert.\n */\n function depositV3Now(\n address depositor,\n address recipient,\n address inputToken,\n address outputToken,\n uint256 inputAmount,\n uint256 outputAmount,\n uint256 destinationChainId,\n address exclusiveRelayer,\n uint32 fillDeadlineOffset,\n uint32 exclusivityDeadline,\n bytes calldata message\n ) external payable {\n depositV3(\n depositor,\n recipient,\n inputToken,\n outputToken,\n inputAmount,\n outputAmount,\n destinationChainId,\n exclusiveRelayer,\n uint32(getCurrentTime()),\n uint32(getCurrentTime()) + fillDeadlineOffset,\n exclusivityDeadline,\n message\n );\n }\n\n /**\n * @notice Submits deposit and sets exclusivityDeadline to current time plus some offset. This function is\n * designed to be called by users who want to set an exclusive relayer for some amount of time after their deposit\n * transaction is mined.\n * @notice If exclusivtyDeadlineOffset > 0, then exclusiveRelayer must be set to a valid address, which is a\n * requirement imposed by depositV3().\n * @param depositor The account credited with the deposit who can request to \"speed up\" this deposit by modifying\n * the output amount, recipient, and message.\n * @param recipient The account receiving funds on the destination chain. Can be an EOA or a contract. If\n * the output token is the wrapped native token for the chain, then the recipient will receive native token if\n * an EOA or wrapped native token if a contract.\n * @param inputToken The token pulled from the caller's account and locked into this contract to\n * initiate the deposit. The equivalent of this token on the relayer's repayment chain of choice will be sent\n * as a refund. If this is equal to the wrapped native token then the caller can optionally pass in native token as\n * msg.value, as long as msg.value = inputTokenAmount.\n * @param outputToken The token that the relayer will send to the recipient on the destination chain. Must be an\n * ERC20.\n * @param inputAmount The amount of input tokens to pull from the caller's account and lock into this contract.\n * This amount will be sent to the relayer on their repayment chain of choice as a refund following an optimistic\n * challenge window in the HubPool, plus a system fee.\n * @param outputAmount The amount of output tokens that the relayer will send to the recipient on the destination.\n * @param destinationChainId The destination chain identifier. Must be enabled along with the input token\n * as a valid deposit route from this spoke pool or this transaction will revert.\n * @param exclusiveRelayer The relayer that will be exclusively allowed to fill this deposit before the\n * exclusivity deadline timestamp.\n * @param quoteTimestamp The HubPool timestamp that is used to determine the system fee paid by the depositor.\n * This must be set to some time between [currentTime - depositQuoteTimeBuffer, currentTime]\n * where currentTime is block.timestamp on this chain or this transaction will revert.\n * @param fillDeadline The deadline for the relayer to fill the deposit. After this destination chain timestamp,\n * the fill will revert on the destination chain. Must be set between [currentTime, currentTime + fillDeadlineBuffer]\n * where currentTime is block.timestamp on this chain or this transaction will revert.\n * @param exclusivityDeadlineOffset Added to the current time to set the exclusive reayer deadline,\n * which is the deadline for the exclusiveRelayer to fill the deposit. After this destination chain timestamp,\n * anyone can fill the deposit.\n * @param message The message to send to the recipient on the destination chain if the recipient is a contract.\n * If the message is not empty, the recipient contract must implement handleV3AcrossMessage() or the fill will revert.\n */\n function depositExclusive(\n address depositor,\n address recipient,\n address inputToken,\n address outputToken,\n uint256 inputAmount,\n uint256 outputAmount,\n uint256 destinationChainId,\n address exclusiveRelayer,\n uint32 quoteTimestamp,\n uint32 fillDeadline,\n uint32 exclusivityDeadlineOffset,\n bytes calldata message\n ) public payable {\n depositV3(\n depositor,\n recipient,\n inputToken,\n outputToken,\n inputAmount,\n outputAmount,\n destinationChainId,\n exclusiveRelayer,\n quoteTimestamp,\n fillDeadline,\n uint32(getCurrentTime()) + exclusivityDeadlineOffset,\n message\n );\n }\n\n /**\n * @notice Depositor can use this function to signal to relayer to use updated output amount, recipient,\n * and/or message.\n * @dev the depositor and depositId must match the params in a V3FundsDeposited event that the depositor\n * wants to speed up. The relayer has the option but not the obligation to use this updated information\n * when filling the deposit via fillV3RelayWithUpdatedDeposit().\n * @param depositor Depositor that must sign the depositorSignature and was the original depositor.\n * @param depositId Deposit ID to speed up.\n * @param updatedOutputAmount New output amount to use for this deposit. Should be lower than previous value\n * otherwise relayer has no incentive to use this updated value.\n * @param updatedRecipient New recipient to use for this deposit. Can be modified if the recipient is a contract\n * that expects to receive a message from the relay and for some reason needs to be modified.\n * @param updatedMessage New message to use for this deposit. Can be modified if the recipient is a contract\n * that expects to receive a message from the relay and for some reason needs to be modified.\n * @param depositorSignature Signed EIP712 hashstruct containing the deposit ID. Should be signed by the depositor\n * account. If depositor is a contract, then should implement EIP1271 to sign as a contract. See\n * _verifyUpdateV3DepositMessage() for more details about how this signature should be constructed.\n */\n function speedUpV3Deposit(\n address depositor,\n uint32 depositId,\n uint256 updatedOutputAmount,\n address updatedRecipient,\n bytes calldata updatedMessage,\n bytes calldata depositorSignature\n ) public override nonReentrant {\n _verifyUpdateV3DepositMessage(\n depositor,\n depositId,\n chainId(),\n updatedOutputAmount,\n updatedRecipient,\n updatedMessage,\n depositorSignature\n );\n\n // Assuming the above checks passed, a relayer can take the signature and the updated deposit information\n // from the following event to submit a fill with updated relay data.\n emit RequestedSpeedUpV3Deposit(\n updatedOutputAmount,\n depositId,\n depositor,\n updatedRecipient,\n updatedMessage,\n depositorSignature\n );\n }\n\n /**************************************\n * RELAYER FUNCTIONS *\n **************************************/\n\n /**\n * @notice Fulfill request to bridge cross chain by sending specified output tokens to the recipient.\n * @dev The fee paid to relayers and the system should be captured in the spread between output\n * amount and input amount when adjusted to be denominated in the input token. A relayer on the destination\n * chain will send outputAmount of outputTokens to the recipient and receive inputTokens on a repayment\n * chain of their choice. Therefore, the fee should account for destination fee transaction costs, the\n * relayer's opportunity cost of capital while they wait to be refunded following an optimistic challenge\n * window in the HubPool, and a system fee charged to relayers.\n * @dev The hash of the relayData will be used to uniquely identify the deposit to fill, so\n * modifying any params in it will result in a different hash and a different deposit. The hash will comprise\n * all parameters passed to depositV3() on the origin chain along with that chain's chainId(). This chain's\n * chainId() must therefore match the destinationChainId passed into depositV3.\n * Relayers are only refunded for filling deposits with deposit hashes that map exactly to the one emitted by the\n * origin SpokePool therefore the relayer should not modify any params in relayData.\n * @dev Cannot fill more than once. Partial fills are not supported.\n * @param relayData struct containing all the data needed to identify the deposit to be filled. Should match\n * all the same-named parameters emitted in the origin chain V3FundsDeposited event.\n * - depositor: The account credited with the deposit who can request to \"speed up\" this deposit by modifying\n * the output amount, recipient, and message.\n * - recipient The account receiving funds on this chain. Can be an EOA or a contract. If\n * the output token is the wrapped native token for the chain, then the recipient will receive native token if\n * an EOA or wrapped native token if a contract.\n * - inputToken: The token pulled from the caller's account to initiate the deposit. The equivalent of this\n * token on the repayment chain will be sent as a refund to the caller.\n * - outputToken The token that the caller will send to the recipient on the destination chain. Must be an\n * ERC20.\n * - inputAmount: This amount, less a system fee, will be sent to the caller on their repayment chain of choice as a refund\n * following an optimistic challenge window in the HubPool.\n * - outputAmount: The amount of output tokens that the caller will send to the recipient.\n * - originChainId: The origin chain identifier.\n * - exclusiveRelayer The relayer that will be exclusively allowed to fill this deposit before the\n * exclusivity deadline timestamp.\n * - fillDeadline The deadline for the caller to fill the deposit. After this timestamp,\n * the fill will revert on the destination chain.\n * - exclusivityDeadline: The deadline for the exclusive relayer to fill the deposit. After this\n * timestamp, anyone can fill this deposit.\n * - message The message to send to the recipient if the recipient is a contract that implements a\n * handleV3AcrossMessage() public function\n * @param repaymentChainId Chain of SpokePool where relayer wants to be refunded after the challenge window has\n * passed. Will receive inputAmount of the equivalent token to inputToken on the repayment chain.\n */\n function fillV3Relay(V3RelayData calldata relayData, uint256 repaymentChainId)\n public\n override\n nonReentrant\n unpausedFills\n {\n // Exclusivity deadline is inclusive and is the latest timestamp that the exclusive relayer has sole right\n // to fill the relay.\n if (relayData.exclusivityDeadline >= getCurrentTime() && relayData.exclusiveRelayer != msg.sender) {\n revert NotExclusiveRelayer();\n }\n\n V3RelayExecutionParams memory relayExecution = V3RelayExecutionParams({\n relay: relayData,\n relayHash: _getV3RelayHash(relayData),\n updatedOutputAmount: relayData.outputAmount,\n updatedRecipient: relayData.recipient,\n updatedMessage: relayData.message,\n repaymentChainId: repaymentChainId\n });\n\n _fillRelayV3(relayExecution, msg.sender, false);\n }\n\n /**\n * @notice Identical to fillV3Relay except that the relayer wants to use a depositor's updated output amount,\n * recipient, and/or message. The relayer should only use this function if they can supply a message signed\n * by the depositor that contains the fill's matching deposit ID along with updated relay parameters.\n * If the signature can be verified, then this function will emit a FilledV3Event that will be used by\n * the system for refund verification purposes. In otherwords, this function is an alternative way to fill a\n * a deposit than fillV3Relay.\n * @dev Subject to same exclusivity deadline rules as fillV3Relay().\n * @param relayData struct containing all the data needed to identify the deposit to be filled. See fillV3Relay().\n * @param repaymentChainId Chain of SpokePool where relayer wants to be refunded after the challenge window has\n * passed. See fillV3Relay().\n * @param updatedOutputAmount New output amount to use for this deposit.\n * @param updatedRecipient New recipient to use for this deposit.\n * @param updatedMessage New message to use for this deposit.\n * @param depositorSignature Signed EIP712 hashstruct containing the deposit ID. Should be signed by the depositor\n * account.\n */\n function fillV3RelayWithUpdatedDeposit(\n V3RelayData calldata relayData,\n uint256 repaymentChainId,\n uint256 updatedOutputAmount,\n address updatedRecipient,\n bytes calldata updatedMessage,\n bytes calldata depositorSignature\n ) public override nonReentrant unpausedFills {\n // Exclusivity deadline is inclusive and is the latest timestamp that the exclusive relayer has sole right\n // to fill the relay.\n if (relayData.exclusivityDeadline >= getCurrentTime() && relayData.exclusiveRelayer != msg.sender) {\n revert NotExclusiveRelayer();\n }\n\n V3RelayExecutionParams memory relayExecution = V3RelayExecutionParams({\n relay: relayData,\n relayHash: _getV3RelayHash(relayData),\n updatedOutputAmount: updatedOutputAmount,\n updatedRecipient: updatedRecipient,\n updatedMessage: updatedMessage,\n repaymentChainId: repaymentChainId\n });\n\n _verifyUpdateV3DepositMessage(\n relayData.depositor,\n relayData.depositId,\n relayData.originChainId,\n updatedOutputAmount,\n updatedRecipient,\n updatedMessage,\n depositorSignature\n );\n\n _fillRelayV3(relayExecution, msg.sender, false);\n }\n\n /**\n * @notice Request Across to send LP funds to this contract to fulfill a slow fill relay\n * for a deposit in the next bundle.\n * @dev Slow fills are not possible unless the input and output tokens are \"equivalent\", i.e.\n * they route to the same L1 token via PoolRebalanceRoutes.\n * @dev Slow fills are created by inserting slow fill objects into a merkle tree that is included\n * in the next HubPool \"root bundle\". Once the optimistic challenge window has passed, the HubPool\n * will relay the slow root to this chain via relayRootBundle(). Once the slow root is relayed,\n * the slow fill can be executed by anyone who calls executeV3SlowRelayLeaf().\n * @dev Cannot request a slow fill if the fill deadline has passed.\n * @dev Cannot request a slow fill if the relay has already been filled or a slow fill has already been requested.\n * @param relayData struct containing all the data needed to identify the deposit that should be\n * slow filled. If any of the params are missing or different from the origin chain deposit,\n * then Across will not include a slow fill for the intended deposit.\n */\n function requestV3SlowFill(V3RelayData calldata relayData) public override nonReentrant unpausedFills {\n // If a depositor has set an exclusivity deadline, then only the exclusive relayer should be able to\n // fast fill within this deadline. Moreover, the depositor should expect to get *fast* filled within\n // this deadline, not slow filled. As a simplifying assumption, we will not allow slow fills to be requested\n // this exclusivity period.\n if (relayData.exclusivityDeadline >= getCurrentTime()) {\n revert NoSlowFillsInExclusivityWindow();\n }\n if (relayData.fillDeadline < getCurrentTime()) revert ExpiredFillDeadline();\n\n bytes32 relayHash = _getV3RelayHash(relayData);\n if (fillStatuses[relayHash] != uint256(FillStatus.Unfilled)) revert InvalidSlowFillRequest();\n fillStatuses[relayHash] = uint256(FillStatus.RequestedSlowFill);\n\n emit RequestedV3SlowFill(\n relayData.inputToken,\n relayData.outputToken,\n relayData.inputAmount,\n relayData.outputAmount,\n relayData.originChainId,\n relayData.depositId,\n relayData.fillDeadline,\n relayData.exclusivityDeadline,\n relayData.exclusiveRelayer,\n relayData.depositor,\n relayData.recipient,\n relayData.message\n );\n }\n\n /**************************************\n * DATA WORKER FUNCTIONS *\n **************************************/\n\n /**\n * @notice Executes a slow relay leaf stored as part of a root bundle relayed by the HubPool.\n * @dev Executing a slow fill leaf is equivalent to filling the relayData so this function cannot be used to\n * double fill a recipient. The relayData that is filled is included in the slowFillLeaf and is hashed\n * like any other fill sent through fillV3Relay().\n * @dev There is no relayer credited with filling this relay since funds are sent directly out of this contract.\n * @param slowFillLeaf Contains all data necessary to uniquely identify a relay for this chain. This struct is\n * hashed and included in a merkle root that is relayed to all spoke pools.\n * - relayData: struct containing all the data needed to identify the original deposit to be slow filled.\n * - chainId: chain identifier where slow fill leaf should be executed. If this doesn't match this chain's\n * chainId, then this function will revert.\n * - updatedOutputAmount: Amount to be sent to recipient out of this contract's balance. Can be set differently\n * from relayData.outputAmount to charge a different fee because this deposit was \"slow\" filled. Usually,\n * this will be set higher to reimburse the recipient for waiting for the slow fill.\n * @param rootBundleId Unique ID of root bundle containing slow relay root that this leaf is contained in.\n * @param proof Inclusion proof for this leaf in slow relay root in root bundle.\n */\n function executeV3SlowRelayLeaf(\n V3SlowFill calldata slowFillLeaf,\n uint32 rootBundleId,\n bytes32[] calldata proof\n ) public override nonReentrant {\n V3RelayData memory relayData = slowFillLeaf.relayData;\n\n _preExecuteLeafHook(relayData.outputToken);\n\n // @TODO In the future consider allowing way for slow fill leaf to be created with updated\n // deposit params like outputAmount, message and recipient.\n V3RelayExecutionParams memory relayExecution = V3RelayExecutionParams({\n relay: relayData,\n relayHash: _getV3RelayHash(relayData),\n updatedOutputAmount: slowFillLeaf.updatedOutputAmount,\n updatedRecipient: relayData.recipient,\n updatedMessage: relayData.message,\n repaymentChainId: EMPTY_REPAYMENT_CHAIN_ID // Repayment not relevant for slow fills.\n });\n\n _verifyV3SlowFill(relayExecution, rootBundleId, proof);\n\n // - No relayer to refund for slow fill executions.\n _fillRelayV3(relayExecution, EMPTY_RELAYER, true);\n }\n\n /**\n * @notice Executes a relayer refund leaf stored as part of a root bundle. Will send the relayer the amount they\n * sent to the recipient plus a relayer fee.\n * @param rootBundleId Unique ID of root bundle containing relayer refund root that this leaf is contained in.\n * @param relayerRefundLeaf Contains all data necessary to reconstruct leaf contained in root bundle and to\n * refund relayer. This data structure is explained in detail in the SpokePoolInterface.\n * @param proof Inclusion proof for this leaf in relayer refund root in root bundle.\n */\n function executeRelayerRefundLeaf(\n uint32 rootBundleId,\n SpokePoolInterface.RelayerRefundLeaf memory relayerRefundLeaf,\n bytes32[] memory proof\n ) public payable virtual override nonReentrant {\n _preExecuteLeafHook(relayerRefundLeaf.l2TokenAddress);\n\n if (relayerRefundLeaf.chainId != chainId()) revert InvalidChainId();\n\n RootBundle storage rootBundle = rootBundles[rootBundleId];\n\n // Check that proof proves that relayerRefundLeaf is contained within the relayer refund root.\n // Note: This should revert if the relayerRefundRoot is uninitialized.\n if (!MerkleLib.verifyRelayerRefund(rootBundle.relayerRefundRoot, relayerRefundLeaf, proof))\n revert InvalidMerkleProof();\n\n _setClaimedLeaf(rootBundleId, relayerRefundLeaf.leafId);\n\n _distributeRelayerRefunds(\n relayerRefundLeaf.chainId,\n relayerRefundLeaf.amountToReturn,\n relayerRefundLeaf.refundAmounts,\n relayerRefundLeaf.leafId,\n relayerRefundLeaf.l2TokenAddress,\n relayerRefundLeaf.refundAddresses\n );\n\n emit ExecutedRelayerRefundRoot(\n relayerRefundLeaf.amountToReturn,\n relayerRefundLeaf.chainId,\n relayerRefundLeaf.refundAmounts,\n rootBundleId,\n relayerRefundLeaf.leafId,\n relayerRefundLeaf.l2TokenAddress,\n relayerRefundLeaf.refundAddresses,\n msg.sender\n );\n }\n\n /**************************************\n * VIEW FUNCTIONS *\n **************************************/\n\n /**\n * @notice Returns chain ID for this network.\n * @dev Some L2s like ZKSync don't support the CHAIN_ID opcode so we allow the implementer to override this.\n */\n function chainId() public view virtual override returns (uint256) {\n return block.chainid;\n }\n\n /**\n * @notice Gets the current time.\n * @return uint for the current timestamp.\n */\n function getCurrentTime() public view virtual returns (uint256) {\n return block.timestamp; // solhint-disable-line not-rely-on-time\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n function _deposit(\n address depositor,\n address recipient,\n address originToken,\n uint256 amount,\n uint256 destinationChainId,\n int64 relayerFeePct,\n uint32 quoteTimestamp,\n bytes memory message\n ) internal {\n // Check that deposit route is enabled.\n if (!enabledDepositRoutes[originToken][destinationChainId]) revert DisabledRoute();\n\n // We limit the relay fees to prevent the user spending all their funds on fees.\n if (SignedMath.abs(relayerFeePct) >= 0.5e18) revert InvalidRelayerFeePct();\n if (amount > MAX_TRANSFER_SIZE) revert MaxTransferSizeExceeded();\n\n // Require that quoteTimestamp has a maximum age so that depositors pay an LP fee based on recent HubPool usage.\n // It is assumed that cross-chain timestamps are normally loosely in-sync, but clock drift can occur. If the\n // SpokePool time stalls or lags significantly, it is still possible to make deposits by setting quoteTimestamp\n // within the configured buffer. The owner should pause deposits if this is undesirable. This will underflow if\n // quoteTimestamp is more than depositQuoteTimeBuffer; this is safe but will throw an unintuitive error.\n\n // slither-disable-next-line timestamp\n if (getCurrentTime() - quoteTimestamp > depositQuoteTimeBuffer) revert InvalidQuoteTimestamp();\n\n // Increment count of deposits so that deposit ID for this spoke pool is unique.\n uint32 newDepositId = numberOfDeposits++;\n\n // If the address of the origin token is a wrappedNativeToken contract and there is a msg.value with the\n // transaction then the user is sending ETH. In this case, the ETH should be deposited to wrappedNativeToken.\n if (originToken == address(wrappedNativeToken) && msg.value > 0) {\n if (msg.value != amount) revert MsgValueDoesNotMatchInputAmount();\n wrappedNativeToken.deposit{ value: msg.value }();\n // Else, it is a normal ERC20. In this case pull the token from the user's wallet as per normal.\n // Note: this includes the case where the L2 user has WETH (already wrapped ETH) and wants to bridge them.\n // In this case the msg.value will be set to 0, indicating a \"normal\" ERC20 bridging action.\n } else IERC20Upgradeable(originToken).safeTransferFrom(msg.sender, address(this), amount);\n\n emit V3FundsDeposited(\n originToken, // inputToken\n address(0), // outputToken. Setting this to 0x0 means that the outputToken should be assumed to be the\n // canonical token for the destination chain matching the inputToken. Therefore, this deposit\n // can always be slow filled.\n // - setting token to 0x0 will signal to off-chain validator that the \"equivalent\"\n // token as the inputToken for the destination chain should be replaced here.\n amount, // inputAmount\n _computeAmountPostFees(amount, relayerFeePct), // outputAmount\n // - output amount will be the deposit amount less relayerFeePct, which should now be set\n // equal to realizedLpFeePct + gasFeePct + capitalCostFeePct where (gasFeePct + capitalCostFeePct)\n // is equal to the old usage of `relayerFeePct`.\n destinationChainId,\n newDepositId,\n quoteTimestamp,\n INFINITE_FILL_DEADLINE, // fillDeadline. Default to infinite expiry because\n // expired deposits refunds could be a breaking change for existing users of this function.\n 0, // exclusivityDeadline. Setting this to 0 along with the exclusiveRelayer to 0x0 means that there\n // is no exclusive deadline\n depositor,\n recipient,\n address(0), // exclusiveRelayer. Setting this to 0x0 will signal to off-chain validator that there\n // is no exclusive relayer.\n message\n );\n }\n\n function _distributeRelayerRefunds(\n uint256 _chainId,\n uint256 amountToReturn,\n uint256[] memory refundAmounts,\n uint32 leafId,\n address l2TokenAddress,\n address[] memory refundAddresses\n ) internal {\n if (refundAddresses.length != refundAmounts.length) revert InvalidMerkleLeaf();\n\n // Send each relayer refund address the associated refundAmount for the L2 token address.\n // Note: Even if the L2 token is not enabled on this spoke pool, we should still refund relayers.\n uint256 length = refundAmounts.length;\n for (uint256 i = 0; i < length; ++i) {\n uint256 amount = refundAmounts[i];\n if (amount > 0) IERC20Upgradeable(l2TokenAddress).safeTransfer(refundAddresses[i], amount);\n }\n\n // If leaf's amountToReturn is positive, then send L2 --> L1 message to bridge tokens back via\n // chain-specific bridging method.\n if (amountToReturn > 0) {\n _bridgeTokensToHubPool(amountToReturn, l2TokenAddress);\n\n emit TokensBridged(amountToReturn, _chainId, leafId, l2TokenAddress, msg.sender);\n }\n }\n\n function _setCrossDomainAdmin(address newCrossDomainAdmin) internal {\n if (newCrossDomainAdmin == address(0)) revert InvalidCrossDomainAdmin();\n crossDomainAdmin = newCrossDomainAdmin;\n emit SetXDomainAdmin(newCrossDomainAdmin);\n }\n\n function _setHubPool(address newHubPool) internal {\n if (newHubPool == address(0)) revert InvalidHubPool();\n hubPool = newHubPool;\n emit SetHubPool(newHubPool);\n }\n\n function _preExecuteLeafHook(address) internal virtual {\n // This method by default is a no-op. Different child spoke pools might want to execute functionality here\n // such as wrapping any native tokens owned by the contract into wrapped tokens before proceeding with\n // executing the leaf.\n }\n\n // Should be overriden by implementing contract depending on how L2 handles sending tokens to L1.\n function _bridgeTokensToHubPool(uint256 amountToReturn, address l2TokenAddress) internal virtual;\n\n function _setClaimedLeaf(uint32 rootBundleId, uint32 leafId) internal {\n RootBundle storage rootBundle = rootBundles[rootBundleId];\n\n // Verify the leafId in the leaf has not yet been claimed.\n if (MerkleLib.isClaimed(rootBundle.claimedBitmap, leafId)) revert ClaimedMerkleLeaf();\n\n // Set leaf as claimed in bitmap. This is passed by reference to the storage rootBundle.\n MerkleLib.setClaimed(rootBundle.claimedBitmap, leafId);\n }\n\n function _verifyUpdateV3DepositMessage(\n address depositor,\n uint32 depositId,\n uint256 originChainId,\n uint256 updatedOutputAmount,\n address updatedRecipient,\n bytes memory updatedMessage,\n bytes memory depositorSignature\n ) internal view {\n // A depositor can request to modify an un-relayed deposit by signing a hash containing the updated\n // details and information uniquely identifying the deposit to relay. This information ensures\n // that this signature cannot be re-used for other deposits.\n // Note: We use the EIP-712 (https://eips.ethereum.org/EIPS/eip-712) standard for hashing and signing typed data.\n // Specifically, we use the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n // `eth_signedTypedDataV4` in MetaMask (https://docs.metamask.io/guide/signing-data.html).\n bytes32 expectedTypedDataV4Hash = _hashTypedDataV4(\n // EIP-712 compliant hash struct: https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct\n keccak256(\n abi.encode(\n UPDATE_V3_DEPOSIT_DETAILS_HASH,\n depositId,\n originChainId,\n updatedOutputAmount,\n updatedRecipient,\n keccak256(updatedMessage)\n )\n ),\n // By passing in the origin chain id, we enable the verification of the signature on a different chain\n originChainId\n );\n _verifyDepositorSignature(depositor, expectedTypedDataV4Hash, depositorSignature);\n }\n\n // This function is isolated and made virtual to allow different L2's to implement chain specific recovery of\n // signers from signatures because some L2s might not support ecrecover. To be safe, consider always reverting\n // this function for L2s where ecrecover is different from how it works on Ethereum, otherwise there is the\n // potential to forge a signature from the depositor using a different private key than the original depositor's.\n function _verifyDepositorSignature(\n address depositor,\n bytes32 ethSignedMessageHash,\n bytes memory depositorSignature\n ) internal view virtual {\n // Note:\n // - We don't need to worry about reentrancy from a contract deployed at the depositor address since the method\n // `SignatureChecker.isValidSignatureNow` is a view method. Re-entrancy can happen, but it cannot affect state.\n // - EIP-1271 signatures are supported. This means that a signature valid now, may not be valid later and vice-versa.\n // - For an EIP-1271 signature to work, the depositor contract address must map to a deployed contract on the destination\n // chain that can validate the signature.\n // - Regular signatures from an EOA are also supported.\n bool isValid = SignatureChecker.isValidSignatureNow(depositor, ethSignedMessageHash, depositorSignature);\n if (!isValid) revert InvalidDepositorSignature();\n }\n\n function _verifyV3SlowFill(\n V3RelayExecutionParams memory relayExecution,\n uint32 rootBundleId,\n bytes32[] memory proof\n ) internal view {\n V3SlowFill memory slowFill = V3SlowFill({\n relayData: relayExecution.relay,\n chainId: chainId(),\n updatedOutputAmount: relayExecution.updatedOutputAmount\n });\n\n if (!MerkleLib.verifyV3SlowRelayFulfillment(rootBundles[rootBundleId].slowRelayRoot, slowFill, proof))\n revert InvalidMerkleProof();\n }\n\n function _computeAmountPostFees(uint256 amount, int256 feesPct) private pure returns (uint256) {\n return (amount * uint256(int256(1e18) - feesPct)) / 1e18;\n }\n\n function _getV3RelayHash(V3RelayData memory relayData) private view returns (bytes32) {\n return keccak256(abi.encode(relayData, chainId()));\n }\n\n // Unwraps ETH and does a transfer to a recipient address. If the recipient is a smart contract then sends wrappedNativeToken.\n function _unwrapwrappedNativeTokenTo(address payable to, uint256 amount) internal {\n if (address(to).isContract()) {\n IERC20Upgradeable(address(wrappedNativeToken)).safeTransfer(to, amount);\n } else {\n wrappedNativeToken.withdraw(amount);\n AddressLibUpgradeable.sendValue(to, amount);\n }\n }\n\n // @param relayer: relayer who is actually credited as filling this deposit. Can be different from\n // exclusiveRelayer if passed exclusivityDeadline or if slow fill.\n function _fillRelayV3(\n V3RelayExecutionParams memory relayExecution,\n address relayer,\n bool isSlowFill\n ) internal {\n V3RelayData memory relayData = relayExecution.relay;\n\n if (relayData.fillDeadline < getCurrentTime()) revert ExpiredFillDeadline();\n\n bytes32 relayHash = relayExecution.relayHash;\n\n // If a slow fill for this fill was requested then the relayFills value for this hash will be\n // FillStatus.RequestedSlowFill. Therefore, if this is the status, then this fast fill\n // will be replacing the slow fill. If this is a slow fill execution, then the following variable\n // is trivially true. We'll emit this value in the FilledRelay\n // event to assist the Dataworker in knowing when to return funds back to the HubPool that can no longer\n // be used for a slow fill execution.\n FillType fillType = isSlowFill\n ? FillType.SlowFill\n : (\n // The following is true if this is a fast fill that was sent after a slow fill request.\n fillStatuses[relayExecution.relayHash] == uint256(FillStatus.RequestedSlowFill)\n ? FillType.ReplacedSlowFill\n : FillType.FastFill\n );\n\n // @dev This function doesn't support partial fills. Therefore, we associate the relay hash with\n // an enum tracking its fill status. All filled relays, whether slow or fast fills, are set to the Filled\n // status. However, we also use this slot to track whether this fill had a slow fill requested. Therefore\n // we can include a bool in the FilledRelay event making it easy for the dataworker to compute if this\n // fill was a fast fill that replaced a slow fill and therefore this SpokePool has excess funds that it\n // needs to send back to the HubPool.\n if (fillStatuses[relayHash] == uint256(FillStatus.Filled)) revert RelayFilled();\n fillStatuses[relayHash] = uint256(FillStatus.Filled);\n\n // @dev Before returning early, emit events to assist the dataworker in being able to know which fills were\n // successful.\n emit FilledV3Relay(\n relayData.inputToken,\n relayData.outputToken,\n relayData.inputAmount,\n relayData.outputAmount,\n relayExecution.repaymentChainId,\n relayData.originChainId,\n relayData.depositId,\n relayData.fillDeadline,\n relayData.exclusivityDeadline,\n relayData.exclusiveRelayer,\n relayer,\n relayData.depositor,\n relayData.recipient,\n relayData.message,\n V3RelayExecutionEventInfo({\n updatedRecipient: relayExecution.updatedRecipient,\n updatedMessage: relayExecution.updatedMessage,\n updatedOutputAmount: relayExecution.updatedOutputAmount,\n fillType: fillType\n })\n );\n\n // If relayer and receiver are the same address, there is no need to do any transfer, as it would result in no\n // net movement of funds.\n // Note: this is important because it means that relayers can intentionally self-relay in a capital efficient\n // way (no need to have funds on the destination).\n // If this is a slow fill, we can't exit early since we still need to send funds out of this contract\n // since there is no \"relayer\".\n address recipientToSend = relayExecution.updatedRecipient;\n\n if (msg.sender == recipientToSend && !isSlowFill) return;\n\n // If relay token is wrappedNativeToken then unwrap and send native token.\n address outputToken = relayData.outputToken;\n uint256 amountToSend = relayExecution.updatedOutputAmount;\n if (outputToken == address(wrappedNativeToken)) {\n // Note: useContractFunds is True if we want to send funds to the recipient directly out of this contract,\n // otherwise we expect the caller to send funds to the recipient. If useContractFunds is True and the\n // recipient wants wrappedNativeToken, then we can assume that wrappedNativeToken is already in the\n // contract, otherwise we'll need the user to send wrappedNativeToken to this contract. Regardless, we'll\n // need to unwrap it to native token before sending to the user.\n if (!isSlowFill) IERC20Upgradeable(outputToken).safeTransferFrom(msg.sender, address(this), amountToSend);\n _unwrapwrappedNativeTokenTo(payable(recipientToSend), amountToSend);\n // Else, this is a normal ERC20 token. Send to recipient.\n } else {\n // Note: Similar to note above, send token directly from the contract to the user in the slow relay case.\n if (!isSlowFill) IERC20Upgradeable(outputToken).safeTransferFrom(msg.sender, recipientToSend, amountToSend);\n else IERC20Upgradeable(outputToken).safeTransfer(recipientToSend, amountToSend);\n }\n\n bytes memory updatedMessage = relayExecution.updatedMessage;\n if (recipientToSend.isContract() && updatedMessage.length > 0) {\n AcrossMessageHandler(recipientToSend).handleV3AcrossMessage(\n outputToken,\n amountToSend,\n msg.sender,\n updatedMessage\n );\n }\n }\n\n // Implementing contract needs to override this to ensure that only the appropriate cross chain admin can execute\n // certain admin functions. For L2 contracts, the cross chain admin refers to some L1 address or contract, and for\n // L1, this would just be the same admin of the HubPool.\n function _requireAdminSender() internal virtual;\n\n // Added to enable the this contract to receive native token (ETH). Used when unwrapping wrappedNativeToken.\n receive() external payable {}\n\n // Reserve storage slots for future versions of this base contract to add state variables without\n // affecting the storage layout of child contracts. Decrement the size of __gap whenever state variables\n // are added. This is at bottom of contract to make sure it's always at the end of storage.\n uint256[999] private __gap;\n}\n" + }, + "contracts/Succinct_SpokePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./SpokePool.sol\";\nimport \"./external/interfaces/SuccinctInterfaces.sol\";\n\n/**\n * @notice Succinct Spoke pool.\n */\ncontract Succinct_SpokePool is SpokePool, ITelepathyHandler {\n // Address of the succinct AMB contract.\n address public succinctTargetAmb;\n\n // Chain where HubPool is deployed that is linked to this SpokePool.\n uint16 public hubChainId;\n\n // Warning: this variable should _never_ be touched outside of this contract. It is intentionally set to be\n // private. Leaving it set to true can permanently disable admin calls.\n bool private adminCallValidated;\n\n event SetSuccinctTargetAmb(address indexed newSuccinctTargetAmb);\n event ReceivedMessageFromL1(address indexed caller, address indexed rootMessageSender);\n\n // Note: validating calls this way ensures that strange calls coming from the succinctTargetAmb won't be\n // misinterpreted. Put differently, just checking that msg.sender == succinctTargetAmb is not sufficient.\n // All calls that have admin privileges must be fired from within the handleTelepathy method that's gone\n // through validation where the sender is checked and the sender from the other chain is also validated.\n // This modifier sets the adminCallValidated variable so this condition can be checked in _requireAdminSender().\n modifier validateInternalCalls() {\n // Make sure adminCallValidated is set to True only once at beginning of processMessageFromRoot, which prevents\n // processMessageFromRoot from being re-entered.\n require(!adminCallValidated, \"adminCallValidated already set\");\n\n // This sets a variable indicating that we're now inside a validated call.\n // Note: this is used by other methods to ensure that this call has been validated by this method and is not\n // spoofed.\n adminCallValidated = true;\n\n _;\n\n // Reset adminCallValidated to false to disallow admin calls after this method exits.\n adminCallValidated = false;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeTokenAddress,\n uint32 _depositQuoteTimeBuffer,\n uint32 _fillDeadlineBuffer\n ) SpokePool(_wrappedNativeTokenAddress, _depositQuoteTimeBuffer, _fillDeadlineBuffer) {} // solhint-disable-line no-empty-blocks\n\n /**\n * @notice Construct the Succinct SpokePool.\n * @param _hubChainId Chain ID of the chain where the HubPool is deployed.\n * @param _succinctTargetAmb Address of the succinct AMB contract.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n */\n function initialize(\n uint16 _hubChainId,\n address _succinctTargetAmb,\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool\n ) public initializer {\n __SpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool);\n succinctTargetAmb = _succinctTargetAmb;\n hubChainId = _hubChainId;\n }\n\n /**\n * @notice Admin can reset the succinct contract address.\n * @param _succinctTargetAmb Address of the succinct AMB contract.\n */\n function setSuccinctTargetAmb(address _succinctTargetAmb) external onlyAdmin {\n succinctTargetAmb = _succinctTargetAmb;\n emit SetSuccinctTargetAmb(_succinctTargetAmb);\n }\n\n /**\n * @notice This will be called by Succinct AMB on this network to relay a message sent from the HubPool.\n * @param _sourceChainId Chain ID of the chain where the message originated.\n * @param _senderAddress Address of the sender on the chain where the message originated.\n * @param _data Data to be received and executed on this contract.\n */\n function handleTelepathy(\n uint16 _sourceChainId,\n address _senderAddress,\n bytes memory _data\n ) external override validateInternalCalls returns (bytes4) {\n // Validate msg.sender as succinct, the x-chain sender as being the hubPool (the admin) and the source chain as\n // 1 (mainnet).\n require(msg.sender == succinctTargetAmb, \"caller not succinct AMB\");\n require(_senderAddress == hubPool, \"sender not hubPool\");\n require(_sourceChainId == hubChainId, \"source chain not hub chain\");\n\n /// @custom:oz-upgrades-unsafe-allow delegatecall\n (bool success, ) = address(this).delegatecall(_data);\n require(success, \"delegatecall failed\");\n\n emit ReceivedMessageFromL1(msg.sender, _senderAddress);\n return ITelepathyHandler.handleTelepathy.selector;\n }\n\n function _bridgeTokensToHubPool(uint256, address) internal override {\n // This method is a no-op. If the chain intends to include bridging functionality, this must be overriden.\n // If not, leaving this unimplemented means this method may be triggered, but the result will be that no\n // balance is transferred.\n }\n\n // Check that the handleTelepathy method has validated the method to ensure the sender is authenticated.\n function _requireAdminSender() internal view override {\n require(adminCallValidated, \"Admin call not validated\");\n }\n}\n" + }, + "contracts/SwapAndBridge.sol": { + "content": "//SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport \"./interfaces/V3SpokePoolInterface.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"./Lockable.sol\";\nimport \"@uma/core/contracts/common/implementation/MultiCaller.sol\";\n\n/**\n * @title SwapAndBridgeBase\n * @notice Base contract for both variants of SwapAndBridge.\n * @custom:security-contact bugs@across.to\n */\nabstract contract SwapAndBridgeBase is Lockable, MultiCaller {\n using SafeERC20 for IERC20;\n\n // This contract performs a low level call with arbirary data to an external contract. This is a large attack\n // surface and we should whitelist which function selectors are allowed to be called on the exchange.\n mapping(bytes4 => bool) public allowedSelectors;\n\n // Across SpokePool we'll submit deposits to with acrossInputToken as the input token.\n V3SpokePoolInterface public immutable SPOKE_POOL;\n\n // Exchange address or router where the swapping will happen.\n address public immutable EXCHANGE;\n\n // Params we'll need caller to pass in to specify an Across Deposit. The input token will be swapped into first\n // before submitting a bridge deposit, which is why we don't include the input token amount as it is not known\n // until after the swap.\n struct DepositData {\n // Token received on destination chain.\n address outputToken;\n // Amount of output token to be received by recipient.\n uint256 outputAmount;\n // The account credited with deposit who can submit speedups to the Across deposit.\n address depositor;\n // The account that will receive the output token on the destination chain. If the output token is\n // wrapped native token, then if this is an EOA then they will receive native token on the destination\n // chain and if this is a contract then they will receive an ERC20.\n address recipient;\n // The destination chain identifier.\n uint256 destinationChainid;\n // The account that can exclusively fill the deposit before the exclusivity deadline.\n address exclusiveRelayer;\n // Timestamp of the deposit used by system to charge fees. Must be within short window of time into the past\n // relative to this chain's current time or deposit will revert.\n uint32 quoteTimestamp;\n // The timestamp on the destination chain after which this deposit can no longer be filled.\n uint32 fillDeadline;\n // The timestamp on the destination chain after which anyone can fill the deposit.\n uint32 exclusivityDeadline;\n // Data that is forwarded to the recipient if the recipient is a contract.\n bytes message;\n }\n\n event SwapBeforeBridge(\n address exchange,\n address indexed swapToken,\n address indexed acrossInputToken,\n uint256 swapTokenAmount,\n uint256 acrossInputAmount,\n address indexed acrossOutputToken,\n uint256 acrossOutputAmount\n );\n\n /****************************************\n * ERRORS *\n ****************************************/\n error MinimumExpectedInputAmount();\n error LeftoverSrcTokens();\n error InvalidFunctionSelector();\n\n /**\n * @notice Construct a new SwapAndBridgeBase contract.\n * @param _spokePool Address of the SpokePool contract that we'll submit deposits to.\n * @param _exchange Address of the exchange where tokens will be swapped.\n * @param _allowedSelectors Function selectors that are allowed to be called on the exchange.\n */\n constructor(\n V3SpokePoolInterface _spokePool,\n address _exchange,\n bytes4[] memory _allowedSelectors\n ) {\n SPOKE_POOL = _spokePool;\n EXCHANGE = _exchange;\n for (uint256 i = 0; i < _allowedSelectors.length; i++) {\n allowedSelectors[_allowedSelectors[i]] = true;\n }\n }\n\n // This contract supports two variants of swap and bridge, one that allows one token and another that allows the caller to pass them in.\n function _swapAndBridge(\n bytes calldata routerCalldata,\n uint256 swapTokenAmount,\n uint256 minExpectedInputTokenAmount,\n DepositData calldata depositData,\n IERC20 _swapToken,\n IERC20 _acrossInputToken\n ) internal {\n // Note: this check should never be impactful, but is here out of an abundance of caution.\n // For example, if the exchange address in the contract is also an ERC20 token that is approved by some\n // user on this contract, a malicious actor could call transferFrom to steal the user's tokens.\n if (!allowedSelectors[bytes4(routerCalldata)]) revert InvalidFunctionSelector();\n\n // Pull tokens from caller into this contract.\n _swapToken.safeTransferFrom(msg.sender, address(this), swapTokenAmount);\n // Swap and run safety checks.\n uint256 srcBalanceBefore = _swapToken.balanceOf(address(this));\n uint256 dstBalanceBefore = _acrossInputToken.balanceOf(address(this));\n\n _swapToken.safeIncreaseAllowance(EXCHANGE, swapTokenAmount);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory result) = EXCHANGE.call(routerCalldata);\n require(success, string(result));\n\n _checkSwapOutputAndDeposit(\n swapTokenAmount,\n srcBalanceBefore,\n dstBalanceBefore,\n minExpectedInputTokenAmount,\n depositData,\n _swapToken,\n _acrossInputToken\n );\n }\n\n /**\n * @notice Check that the swap returned enough tokens to submit an Across deposit with and then submit the deposit.\n * @param swapTokenAmount Amount of swapToken to swap for a minimum amount of acrossInputToken.\n * @param swapTokenBalanceBefore Balance of swapToken before swap.\n * @param inputTokenBalanceBefore Amount of Across input token we held before swap\n * @param minExpectedInputTokenAmount Minimum amount of received acrossInputToken that we'll bridge\n **/\n function _checkSwapOutputAndDeposit(\n uint256 swapTokenAmount,\n uint256 swapTokenBalanceBefore,\n uint256 inputTokenBalanceBefore,\n uint256 minExpectedInputTokenAmount,\n DepositData calldata depositData,\n IERC20 _swapToken,\n IERC20 _acrossInputToken\n ) internal {\n // Sanity check that we received as many tokens as we require:\n uint256 returnAmount = _acrossInputToken.balanceOf(address(this)) - inputTokenBalanceBefore;\n // Sanity check that received amount from swap is enough to submit Across deposit with.\n if (returnAmount < minExpectedInputTokenAmount) revert MinimumExpectedInputAmount();\n // Sanity check that we don't have any leftover swap tokens that would be locked in this contract (i.e. check\n // that we weren't partial filled).\n if (swapTokenBalanceBefore - _swapToken.balanceOf(address(this)) != swapTokenAmount) revert LeftoverSrcTokens();\n\n emit SwapBeforeBridge(\n EXCHANGE,\n address(_swapToken),\n address(_acrossInputToken),\n swapTokenAmount,\n returnAmount,\n depositData.outputToken,\n depositData.outputAmount\n );\n // Deposit the swapped tokens into Across and bridge them using remainder of input params.\n _acrossInputToken.safeIncreaseAllowance(address(SPOKE_POOL), returnAmount);\n SPOKE_POOL.depositV3(\n depositData.depositor,\n depositData.recipient,\n address(_acrossInputToken), // input token\n depositData.outputToken, // output token\n returnAmount, // input amount.\n depositData.outputAmount, // output amount\n depositData.destinationChainid,\n depositData.exclusiveRelayer,\n depositData.quoteTimestamp,\n depositData.fillDeadline,\n depositData.exclusivityDeadline,\n depositData.message\n );\n }\n}\n\n/**\n * @title SwapAndBridge\n * @notice Allows caller to swap between two pre-specified tokens on a chain before bridging the received token\n * via Across atomically. Provides safety checks post-swap and before-deposit.\n * @dev This variant primarily exists\n */\ncontract SwapAndBridge is SwapAndBridgeBase {\n using SafeERC20 for IERC20;\n\n // This contract simply enables the caller to swap a token on this chain for another specified one\n // and bridge it as the input token via Across. This simplification is made to make the code\n // easier to reason about and solve a specific use case for Across.\n IERC20 public immutable SWAP_TOKEN;\n\n // The token that will be bridged via Across as the inputToken.\n IERC20 public immutable ACROSS_INPUT_TOKEN;\n\n /**\n * @notice Construct a new SwapAndBridge contract.\n * @param _spokePool Address of the SpokePool contract that we'll submit deposits to.\n * @param _exchange Address of the exchange where tokens will be swapped.\n * @param _allowedSelectors Function selectors that are allowed to be called on the exchange.\n * @param _swapToken Address of the token that will be swapped for acrossInputToken. Cannot be 0x0\n * @param _acrossInputToken Address of the token that will be bridged via Across as the inputToken.\n */\n constructor(\n V3SpokePoolInterface _spokePool,\n address _exchange,\n bytes4[] memory _allowedSelectors,\n IERC20 _swapToken,\n IERC20 _acrossInputToken\n ) SwapAndBridgeBase(_spokePool, _exchange, _allowedSelectors) {\n SWAP_TOKEN = _swapToken;\n ACROSS_INPUT_TOKEN = _acrossInputToken;\n }\n\n /**\n * @notice Swaps tokens on this chain via specified router before submitting Across deposit atomically.\n * Caller can specify their slippage tolerance for the swap and Across deposit params.\n * @dev If swapToken or acrossInputToken are the native token for this chain then this function might fail.\n * the assumption is that this function will handle only ERC20 tokens.\n * @param routerCalldata ABI encoded function data to call on router. Should form a swap of swapToken for\n * enough of acrossInputToken, otherwise this function will revert.\n * @param swapTokenAmount Amount of swapToken to swap for a minimum amount of depositData.inputToken.\n * @param minExpectedInputTokenAmount Minimum amount of received depositData.inputToken that we'll submit bridge\n * deposit with.\n * @param depositData Specifies the Across deposit params we'll send after the swap.\n */\n function swapAndBridge(\n bytes calldata routerCalldata,\n uint256 swapTokenAmount,\n uint256 minExpectedInputTokenAmount,\n DepositData calldata depositData\n ) external nonReentrant {\n _swapAndBridge(\n routerCalldata,\n swapTokenAmount,\n minExpectedInputTokenAmount,\n depositData,\n SWAP_TOKEN,\n ACROSS_INPUT_TOKEN\n );\n }\n}\n\n/**\n * @title UniversalSwapAndBridge\n * @notice Allows caller to swap between any two tokens specified at runtime on a chain before\n * bridging the received token via Across atomically. Provides safety checks post-swap and before-deposit.\n */\ncontract UniversalSwapAndBridge is SwapAndBridgeBase {\n /**\n * @notice Construct a new SwapAndBridgeBase contract.\n * @param _spokePool Address of the SpokePool contract that we'll submit deposits to.\n * @param _exchange Address of the exchange where tokens will be swapped.\n * @param _allowedSelectors Function selectors that are allowed to be called on the exchange.\n */\n constructor(\n V3SpokePoolInterface _spokePool,\n address _exchange,\n bytes4[] memory _allowedSelectors\n ) SwapAndBridgeBase(_spokePool, _exchange, _allowedSelectors) {}\n\n /**\n * @notice Swaps tokens on this chain via specified router before submitting Across deposit atomically.\n * Caller can specify their slippage tolerance for the swap and Across deposit params.\n * @dev If swapToken or acrossInputToken are the native token for this chain then this function might fail.\n * the assumption is that this function will handle only ERC20 tokens.\n * @param swapToken Address of the token that will be swapped for acrossInputToken.\n * @param acrossInputToken Address of the token that will be bridged via Across as the inputToken.\n * @param routerCalldata ABI encoded function data to call on router. Should form a swap of swapToken for\n * enough of acrossInputToken, otherwise this function will revert.\n * @param swapTokenAmount Amount of swapToken to swap for a minimum amount of depositData.inputToken.\n * @param minExpectedInputTokenAmount Minimum amount of received depositData.inputToken that we'll submit bridge\n * deposit with.\n * @param depositData Specifies the Across deposit params we'll send after the swap.\n */\n function swapAndBridge(\n IERC20 swapToken,\n IERC20 acrossInputToken,\n bytes calldata routerCalldata,\n uint256 swapTokenAmount,\n uint256 minExpectedInputTokenAmount,\n DepositData calldata depositData\n ) external nonReentrant {\n _swapAndBridge(\n routerCalldata,\n swapTokenAmount,\n minExpectedInputTokenAmount,\n depositData,\n swapToken,\n acrossInputToken\n );\n }\n}\n" + }, + "contracts/test/AcrossMessageHandlerMock.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"../SpokePool.sol\";\nimport \"../interfaces/V3SpokePoolInterface.sol\";\n\ncontract AcrossMessageHandlerMock is AcrossMessageHandler {\n function handleV3AcrossMessage(\n address tokenSent,\n uint256 amount,\n address relayer,\n bytes memory message\n ) external override {}\n}\n" + }, + "contracts/test/ArbitrumMocks.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\ncontract ArbitrumMockErc20GatewayRouter {\n function outboundTransferCustomRefund(\n address,\n address,\n address,\n uint256,\n uint256,\n uint256,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n return _data;\n }\n\n function outboundTransfer(\n address,\n address,\n uint256,\n uint256,\n uint256,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n return _data;\n }\n\n function getGateway(address) external view returns (address) {\n return address(this);\n }\n}\n" + }, + "contracts/test/interfaces/MockV2SpokePoolInterface.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @notice Contains common data structures and functions used by all SpokePool implementations.\n */\ninterface MockV2SpokePoolInterface {\n struct RelayData {\n address depositor;\n address recipient;\n address destinationToken;\n uint256 amount;\n uint256 originChainId;\n uint256 destinationChainId;\n int64 realizedLpFeePct;\n int64 relayerFeePct;\n uint32 depositId;\n bytes message;\n }\n\n struct RelayExecution {\n RelayData relay;\n bytes32 relayHash;\n int64 updatedRelayerFeePct;\n address updatedRecipient;\n bytes updatedMessage;\n uint256 repaymentChainId;\n uint256 maxTokensToSend;\n uint256 maxCount;\n bool slowFill;\n int256 payoutAdjustmentPct;\n }\n\n struct SlowFill {\n RelayData relayData;\n int256 payoutAdjustmentPct;\n }\n}\n" + }, + "contracts/test/MerkleLibTest.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"../MerkleLib.sol\";\nimport \"../interfaces/HubPoolInterface.sol\";\nimport \"../interfaces/SpokePoolInterface.sol\";\nimport \"./interfaces/MockV2SpokePoolInterface.sol\";\nimport \"./V2MerkleLib.sol\";\n\n/**\n * @notice Contract to test the MerkleLib.\n */\ncontract MerkleLibTest {\n mapping(uint256 => uint256) public claimedBitMap;\n\n uint256 public claimedBitMap1D;\n\n function verifyPoolRebalance(\n bytes32 root,\n HubPoolInterface.PoolRebalanceLeaf memory rebalance,\n bytes32[] memory proof\n ) public pure returns (bool) {\n return MerkleLib.verifyPoolRebalance(root, rebalance, proof);\n }\n\n function verifyRelayerRefund(\n bytes32 root,\n SpokePoolInterface.RelayerRefundLeaf memory refund,\n bytes32[] memory proof\n ) public pure returns (bool) {\n return MerkleLib.verifyRelayerRefund(root, refund, proof);\n }\n\n function verifySlowRelayFulfillment(\n bytes32 root,\n MockV2SpokePoolInterface.SlowFill memory slowFill,\n bytes32[] memory proof\n ) public pure returns (bool) {\n return V2MerkleLib.verifySlowRelayFulfillment(root, slowFill, proof);\n }\n\n function verifyV3SlowRelayFulfillment(\n bytes32 root,\n V3SpokePoolInterface.V3SlowFill memory slowFill,\n bytes32[] memory proof\n ) public pure returns (bool) {\n return MerkleLib.verifyV3SlowRelayFulfillment(root, slowFill, proof);\n }\n\n function isClaimed(uint256 index) public view returns (bool) {\n return MerkleLib.isClaimed(claimedBitMap, index);\n }\n\n function setClaimed(uint256 index) public {\n MerkleLib.setClaimed(claimedBitMap, index);\n }\n\n function isClaimed1D(uint8 index) public view returns (bool) {\n return MerkleLib.isClaimed1D(claimedBitMap1D, index);\n }\n\n function setClaimed1D(uint8 index) public {\n claimedBitMap1D = MerkleLib.setClaimed1D(claimedBitMap1D, index);\n }\n}\n" + }, + "contracts/test/MockBedrockStandardBridge.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"../Ovm_SpokePool.sol\";\n\n// Provides payable withdrawTo interface introduced on Bedrock\ncontract MockBedrockL2StandardBridge is IL2ERC20Bridge {\n function withdrawTo(\n address _l2Token,\n address _to,\n uint256 _amount,\n uint32 _minGasLimit,\n bytes calldata _extraData\n ) external payable {\n // do nothing\n }\n\n function bridgeERC20To(\n address _localToken,\n address _remoteToken,\n address _to,\n uint256 _amount,\n uint256 _minGasLimit,\n bytes calldata _extraData\n ) external {\n // Check that caller has approved this contract to pull funds, mirroring mainnet's behavior\n IERC20(_localToken).transferFrom(msg.sender, address(this), _amount);\n // do nothing\n }\n}\n" + }, + "contracts/test/MockBlastUsdYieldManager.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport { USDYieldManager } from \"../Blast_DaiRetriever.sol\";\n\ncontract MockBlastUsdYieldManager is USDYieldManager {\n bool public shouldFail;\n\n constructor() {\n shouldFail = false;\n }\n\n function setShouldFail(bool _shouldFail) external {\n shouldFail = _shouldFail;\n }\n\n function claimWithdrawal(uint256 _requestId, uint256 _hintId) external returns (bool success) {\n success = !shouldFail;\n }\n}\n" + }, + "contracts/test/MockCaller.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"../interfaces/SpokePoolInterface.sol\";\n\n// Used for calling SpokePool.sol functions from a contract instead of an EOA. Can be used to simulate aggregator\n// or pooled relayer behavior. Makes all calls from constructor to make sure SpokePool is not relying on checking the\n// caller's code size which is 0 at construction time.\n\ncontract MockCaller {\n constructor(\n address _spokePool,\n uint32 rootBundleId,\n SpokePoolInterface.RelayerRefundLeaf memory relayerRefundLeaf,\n bytes32[] memory proof\n ) {\n require(_spokePool != address(this), \"spokePool not external\");\n SpokePoolInterface(_spokePool).executeRelayerRefundLeaf(rootBundleId, relayerRefundLeaf, proof);\n }\n}\n" + }, + "contracts/test/MockERC1271.sol": { + "content": "//SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/interfaces/IERC1271.sol\";\n\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title MockERC1271\n * @notice Implements mocked ERC1271 contract for testing.\n */\ncontract MockERC1271 is IERC1271, Ownable {\n constructor(address originalOwner) {\n transferOwnership(originalOwner);\n }\n\n function isValidSignature(bytes32 hash, bytes memory signature) public view override returns (bytes4 magicValue) {\n return ECDSA.recover(hash, signature) == owner() ? this.isValidSignature.selector : bytes4(0);\n }\n}\n" + }, + "contracts/test/MockHubPool.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title MockHubPool for Token Relay between Layer 1 and Layer 2\n/// @dev This contract acts as a mock implementation for testing purposes,\n/// simulating the behavior of a hub pool that can relay tokens and messages\n/// between Ethereum (Layer 1) and a Layer 2 solution like Optimism.\n/// It delegates calls to an external chain adapter contract for actual execution.\ncontract MockHubPool {\n /// @notice Emitted when the adapter contract address is changed.\n event AdapterChanged(address indexed oldAdapter, address indexed newAdapter);\n\n /// @notice The address of the contract owner, set to the deployer of the contract.\n address public immutable owner;\n /// @notice The address of the adapter contract responsible for handling\n /// token relay and message passing to Layer 2.\n address public adapter;\n\n /// @notice Creates a new MockHubPool and sets the owner and initial adapter.\n /// @param _adapter The address of the initial adapter contract.\n constructor(address _adapter) {\n adapter = _adapter;\n owner = msg.sender; // Set the contract deployer as the owner\n }\n\n /// @notice Ensures that a function is callable only by the contract owner.\n modifier onlyOwner() {\n require(msg.sender == owner, \"Caller is not the owner\");\n _;\n }\n\n /// @notice Fallback function to receive ETH.\n fallback() external payable {} // solhint-disable-line no-empty-blocks\n\n /// @notice Receive function to handle direct ETH transfers.\n receive() external payable {} // solhint-disable-line no-empty-blocks\n\n /// @notice Changes the adapter contract address.\n /// @dev This function can only be called by the contract owner.\n /// @param _adapter The new adapter contract address.\n function changeAdapter(address _adapter) public onlyOwner {\n require(_adapter != address(0), \"NO_ZERO_ADDRESS\");\n address _oldAdapter = adapter;\n adapter = _adapter;\n emit AdapterChanged(_oldAdapter, _adapter);\n }\n\n /// @notice Relays tokens from L1 to L2 using the adapter contract.\n /// @dev This function delegates the call to the adapter contract.\n /// @param l1Token The address of the L1 token to relay.\n /// @param l2Token The address of the L2 token to receive.\n /// @param amount The amount of tokens to relay.\n /// @param to The address on L2 to receive the tokens.\n function relayTokens(\n address l1Token,\n address l2Token,\n uint256 amount,\n address to\n ) external {\n (bool success, ) = adapter.delegatecall(\n abi.encodeWithSignature(\n \"relayTokens(address,address,uint256,address)\",\n l1Token, // l1Token.\n l2Token, // l2Token.\n amount, // amount.\n to // to. This should be the spokePool.\n )\n );\n require(success, \"delegatecall failed\");\n }\n\n /// @notice Queries the balance of a user for a specific L2 token using the adapter contract.\n /// @dev This function delegates the call to the adapter contract to execute the balance check.\n /// @param l2Token The address of the L2 token.\n /// @param user The user address whose balance is being queried.\n function balanceOf(address l2Token, address user) external {\n (bool success, ) = adapter.delegatecall(\n abi.encodeWithSignature(\n \"relayMessage(address,bytes)\",\n l2Token,\n abi.encodeWithSignature(\"balanceOf(address)\", user) // message\n )\n );\n require(success, \"delegatecall failed\");\n }\n\n /// @notice Relays an arbitrary message to the L2 chain via the adapter contract.\n /// @dev This function delegates the call to the adapter contract to execute the message relay.\n /// @param target The address of the target contract on L2.\n /// @param l2CallData The calldata to send to the target contract on L2. (must be abi encoded)\n function arbitraryMessage(address target, bytes memory l2CallData) external {\n (bool success, ) = adapter.delegatecall(\n abi.encodeWithSignature(\"relayMessage(address,bytes)\", target, l2CallData)\n );\n require(success, \"delegatecall failed\");\n }\n}\n" + }, + "contracts/test/MockOptimism_SpokePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\nimport \"../Ovm_SpokePool.sol\";\n\n/**\n * @notice Mock Optimism Spoke pool allowing deployer to override constructor params.\n */\ncontract MockOptimism_SpokePool is Ovm_SpokePool {\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _wrappedNativeTokenAddress)\n Ovm_SpokePool(_wrappedNativeTokenAddress, 1 hours, 9 hours, IERC20(address(0)), ITokenMessenger(address(0)))\n {} // solhint-disable-line no-empty-blocks\n\n function initialize(\n address l2Eth,\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool\n ) public initializer {\n __OvmSpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool, l2Eth);\n }\n}\n" + }, + "contracts/test/MockSpokePool.sol": { + "content": "//SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"../SpokePool.sol\";\nimport \"./interfaces/MockV2SpokePoolInterface.sol\";\nimport \"./V2MerkleLib.sol\";\n\n/**\n * @title MockSpokePool\n * @notice Implements abstract contract for testing.\n */\ncontract MockSpokePool is SpokePool, MockV2SpokePoolInterface, OwnableUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 private chainId_;\n uint256 private currentTime;\n mapping(bytes32 => uint256) private relayFills;\n\n uint256 public constant SLOW_FILL_MAX_TOKENS_TO_SEND = 1e40;\n\n bytes32 public constant UPDATE_DEPOSIT_DETAILS_HASH =\n keccak256(\n \"UpdateDepositDetails(uint32 depositId,uint256 originChainId,int64 updatedRelayerFeePct,address updatedRecipient,bytes updatedMessage)\"\n );\n\n event BridgedToHubPool(uint256 amount, address token);\n event PreLeafExecuteHook(address token);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _wrappedNativeTokenAddress) SpokePool(_wrappedNativeTokenAddress, 1 hours, 9 hours) {} // solhint-disable-line no-empty-blocks\n\n function initialize(\n uint32 _initialDepositId,\n address _crossDomainAdmin,\n address _hubPool\n ) public initializer {\n __Ownable_init();\n __SpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool);\n currentTime = block.timestamp; // solhint-disable-line not-rely-on-time\n }\n\n function setCurrentTime(uint256 time) external {\n currentTime = time;\n }\n\n function distributeRelayerRefunds(\n uint256 _chainId,\n uint256 amountToReturn,\n uint256[] memory refundAmounts,\n uint32 leafId,\n address l2TokenAddress,\n address[] memory refundAddresses\n ) external {\n _distributeRelayerRefunds(_chainId, amountToReturn, refundAmounts, leafId, l2TokenAddress, refundAddresses);\n }\n\n function _verifyUpdateDepositMessage(\n address depositor,\n uint32 depositId,\n uint256 originChainId,\n int64 updatedRelayerFeePct,\n address updatedRecipient,\n bytes memory updatedMessage,\n bytes memory depositorSignature\n ) internal view {\n bytes32 expectedTypedDataV4Hash = _hashTypedDataV4(\n // EIP-712 compliant hash struct: https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct\n keccak256(\n abi.encode(\n UPDATE_DEPOSIT_DETAILS_HASH,\n depositId,\n originChainId,\n updatedRelayerFeePct,\n updatedRecipient,\n keccak256(updatedMessage)\n )\n ),\n // By passing in the origin chain id, we enable the verification of the signature on a different chain\n originChainId\n );\n _verifyDepositorSignature(depositor, expectedTypedDataV4Hash, depositorSignature);\n }\n\n function verifyUpdateV3DepositMessage(\n address depositor,\n uint32 depositId,\n uint256 originChainId,\n uint256 updatedOutputAmount,\n address updatedRecipient,\n bytes memory updatedMessage,\n bytes memory depositorSignature\n ) public view {\n return\n _verifyUpdateV3DepositMessage(\n depositor,\n depositId,\n originChainId,\n updatedOutputAmount,\n updatedRecipient,\n updatedMessage,\n depositorSignature\n );\n }\n\n function fillRelayV3Internal(\n V3RelayExecutionParams memory relayExecution,\n address relayer,\n bool isSlowFill\n ) external {\n _fillRelayV3(relayExecution, relayer, isSlowFill);\n }\n\n // This function is nonReentrant in order to allow caller to test whether a different function\n // is reentrancy protected or not.\n function callback(bytes memory data) external payable nonReentrant {\n (bool success, bytes memory result) = address(this).call{ value: msg.value }(data);\n require(success, string(result));\n }\n\n function setFillStatus(bytes32 relayHash, FillType fillType) external {\n fillStatuses[relayHash] = uint256(fillType);\n }\n\n function getCurrentTime() public view override returns (uint256) {\n return currentTime;\n }\n\n function _preExecuteLeafHook(address token) internal override {\n emit PreLeafExecuteHook(token);\n }\n\n function _bridgeTokensToHubPool(uint256 amount, address token) internal override {\n emit BridgedToHubPool(amount, token);\n }\n\n function _requireAdminSender() internal override onlyOwner {} // solhint-disable-line no-empty-blocks\n\n function chainId() public view override(SpokePool) returns (uint256) {\n // If chainId_ is set then return it, else do nothing and return the parent chainId().\n return chainId_ == 0 ? super.chainId() : chainId_;\n }\n\n function setChainId(uint256 _chainId) public {\n chainId_ = _chainId;\n }\n\n function depositV2(\n address recipient,\n address originToken,\n uint256 amount,\n uint256 destinationChainId,\n int64 relayerFeePct,\n uint32 quoteTimestamp,\n bytes memory message,\n uint256 // maxCount\n ) public payable virtual nonReentrant unpausedDeposits {\n // Increment count of deposits so that deposit ID for this spoke pool is unique.\n uint32 newDepositId = numberOfDeposits++;\n\n if (originToken == address(wrappedNativeToken) && msg.value > 0) {\n require(msg.value == amount);\n wrappedNativeToken.deposit{ value: msg.value }();\n } else IERC20Upgradeable(originToken).safeTransferFrom(msg.sender, address(this), amount);\n\n emit FundsDeposited(\n amount,\n chainId(),\n destinationChainId,\n relayerFeePct,\n newDepositId,\n quoteTimestamp,\n originToken,\n recipient,\n msg.sender,\n message\n );\n }\n\n function speedUpDeposit(\n address depositor,\n int64 updatedRelayerFeePct,\n uint32 depositId,\n address updatedRecipient,\n bytes memory updatedMessage,\n bytes memory depositorSignature\n ) public nonReentrant {\n require(SignedMath.abs(updatedRelayerFeePct) < 0.5e18, \"Invalid relayer fee\");\n\n _verifyUpdateDepositMessage(\n depositor,\n depositId,\n chainId(),\n updatedRelayerFeePct,\n updatedRecipient,\n updatedMessage,\n depositorSignature\n );\n\n // Assuming the above checks passed, a relayer can take the signature and the updated relayer fee information\n // from the following event to submit a fill with an updated fee %.\n emit RequestedSpeedUpDeposit(\n updatedRelayerFeePct,\n depositId,\n depositor,\n updatedRecipient,\n updatedMessage,\n depositorSignature\n );\n }\n\n function fillRelay(\n address depositor,\n address recipient,\n address destinationToken,\n uint256 amount,\n uint256 maxTokensToSend,\n uint256 repaymentChainId,\n uint256 originChainId,\n int64 realizedLpFeePct,\n int64 relayerFeePct,\n uint32 depositId,\n bytes memory message,\n uint256 maxCount\n ) public nonReentrant unpausedFills {\n RelayExecution memory relayExecution = RelayExecution({\n relay: MockV2SpokePoolInterface.RelayData({\n depositor: depositor,\n recipient: recipient,\n destinationToken: destinationToken,\n amount: amount,\n realizedLpFeePct: realizedLpFeePct,\n relayerFeePct: relayerFeePct,\n depositId: depositId,\n originChainId: originChainId,\n destinationChainId: chainId(),\n message: message\n }),\n relayHash: bytes32(0),\n updatedRelayerFeePct: relayerFeePct,\n updatedRecipient: recipient,\n updatedMessage: message,\n repaymentChainId: repaymentChainId,\n maxTokensToSend: maxTokensToSend,\n slowFill: false,\n payoutAdjustmentPct: 0,\n maxCount: maxCount\n });\n relayExecution.relayHash = _getRelayHash(relayExecution.relay);\n\n uint256 fillAmountPreFees = _fillRelay(relayExecution);\n _emitFillRelay(relayExecution, fillAmountPreFees);\n }\n\n function executeSlowRelayLeaf(\n address depositor,\n address recipient,\n address destinationToken,\n uint256 amount,\n uint256 originChainId,\n int64 realizedLpFeePct,\n int64 relayerFeePct,\n uint32 depositId,\n uint32 rootBundleId,\n bytes memory message,\n int256 payoutAdjustment,\n bytes32[] memory proof\n ) public nonReentrant {\n _executeSlowRelayLeaf(\n depositor,\n recipient,\n destinationToken,\n amount,\n originChainId,\n chainId(),\n realizedLpFeePct,\n relayerFeePct,\n depositId,\n rootBundleId,\n message,\n payoutAdjustment,\n proof\n );\n }\n\n function fillRelayWithUpdatedDeposit(\n address depositor,\n address recipient,\n address updatedRecipient,\n address destinationToken,\n uint256 amount,\n uint256 maxTokensToSend,\n uint256 repaymentChainId,\n uint256 originChainId,\n int64 realizedLpFeePct,\n int64 relayerFeePct,\n int64 updatedRelayerFeePct,\n uint32 depositId,\n bytes memory message,\n bytes memory updatedMessage,\n bytes memory depositorSignature,\n uint256 maxCount\n ) public nonReentrant unpausedFills {\n RelayExecution memory relayExecution = RelayExecution({\n relay: MockV2SpokePoolInterface.RelayData({\n depositor: depositor,\n recipient: recipient,\n destinationToken: destinationToken,\n amount: amount,\n realizedLpFeePct: realizedLpFeePct,\n relayerFeePct: relayerFeePct,\n depositId: depositId,\n originChainId: originChainId,\n destinationChainId: chainId(),\n message: message\n }),\n relayHash: bytes32(0),\n updatedRelayerFeePct: updatedRelayerFeePct,\n updatedRecipient: updatedRecipient,\n updatedMessage: updatedMessage,\n repaymentChainId: repaymentChainId,\n maxTokensToSend: maxTokensToSend,\n slowFill: false,\n payoutAdjustmentPct: 0,\n maxCount: maxCount\n });\n relayExecution.relayHash = _getRelayHash(relayExecution.relay);\n\n _verifyUpdateDepositMessage(\n depositor,\n depositId,\n originChainId,\n updatedRelayerFeePct,\n updatedRecipient,\n updatedMessage,\n depositorSignature\n );\n uint256 fillAmountPreFees = _fillRelay(relayExecution);\n _emitFillRelay(relayExecution, fillAmountPreFees);\n }\n\n function _executeSlowRelayLeaf(\n address depositor,\n address recipient,\n address destinationToken,\n uint256 amount,\n uint256 originChainId,\n uint256 destinationChainId,\n int64 realizedLpFeePct,\n int64 relayerFeePct,\n uint32 depositId,\n uint32 rootBundleId,\n bytes memory message,\n int256 payoutAdjustmentPct,\n bytes32[] memory proof\n ) internal {\n RelayExecution memory relayExecution = RelayExecution({\n relay: MockV2SpokePoolInterface.RelayData({\n depositor: depositor,\n recipient: recipient,\n destinationToken: destinationToken,\n amount: amount,\n realizedLpFeePct: realizedLpFeePct,\n relayerFeePct: relayerFeePct,\n depositId: depositId,\n originChainId: originChainId,\n destinationChainId: destinationChainId,\n message: message\n }),\n relayHash: bytes32(0),\n updatedRelayerFeePct: 0,\n updatedRecipient: recipient,\n updatedMessage: message,\n repaymentChainId: 0,\n maxTokensToSend: SLOW_FILL_MAX_TOKENS_TO_SEND,\n slowFill: true,\n payoutAdjustmentPct: payoutAdjustmentPct,\n maxCount: type(uint256).max\n });\n relayExecution.relayHash = _getRelayHash(relayExecution.relay);\n\n _verifySlowFill(relayExecution, rootBundleId, proof);\n\n uint256 fillAmountPreFees = _fillRelay(relayExecution);\n\n _emitFillRelay(relayExecution, fillAmountPreFees);\n }\n\n function _computeAmountPreFees(uint256 amount, int64 feesPct) private pure returns (uint256) {\n return (1e18 * amount) / uint256((int256(1e18) - feesPct));\n }\n\n function __computeAmountPostFees(uint256 amount, int256 feesPct) private pure returns (uint256) {\n return (amount * uint256(int256(1e18) - feesPct)) / 1e18;\n }\n\n function _getRelayHash(MockV2SpokePoolInterface.RelayData memory relayData) private pure returns (bytes32) {\n return keccak256(abi.encode(relayData));\n }\n\n function _fillRelay(RelayExecution memory relayExecution) internal returns (uint256 fillAmountPreFees) {\n MockV2SpokePoolInterface.RelayData memory relayData = relayExecution.relay;\n\n require(relayFills[relayExecution.relayHash] < relayData.amount, \"relay filled\");\n\n fillAmountPreFees = _computeAmountPreFees(\n relayExecution.maxTokensToSend,\n (relayData.realizedLpFeePct + relayExecution.updatedRelayerFeePct)\n );\n require(fillAmountPreFees > 0, \"fill amount pre fees is 0\");\n\n uint256 amountRemainingInRelay = relayData.amount - relayFills[relayExecution.relayHash];\n if (amountRemainingInRelay < fillAmountPreFees) {\n fillAmountPreFees = amountRemainingInRelay;\n }\n\n uint256 amountToSend = __computeAmountPostFees(\n fillAmountPreFees,\n relayData.realizedLpFeePct + relayExecution.updatedRelayerFeePct\n );\n\n if (relayExecution.payoutAdjustmentPct != 0) {\n require(relayExecution.payoutAdjustmentPct >= -1e18, \"payoutAdjustmentPct too small\");\n require(relayExecution.payoutAdjustmentPct <= 100e18, \"payoutAdjustmentPct too large\");\n\n amountToSend = __computeAmountPostFees(amountToSend, -relayExecution.payoutAdjustmentPct);\n require(amountToSend <= relayExecution.maxTokensToSend, \"Somehow hit maxTokensToSend!\");\n }\n\n bool localRepayment = relayExecution.repaymentChainId == relayExecution.relay.destinationChainId;\n require(\n localRepayment || relayExecution.relay.amount == fillAmountPreFees || relayExecution.slowFill,\n \"invalid repayment chain\"\n );\n\n relayFills[relayExecution.relayHash] += fillAmountPreFees;\n\n if (msg.sender == relayExecution.updatedRecipient && !relayExecution.slowFill) return fillAmountPreFees;\n\n if (relayData.destinationToken == address(wrappedNativeToken)) {\n if (!relayExecution.slowFill)\n IERC20Upgradeable(relayData.destinationToken).safeTransferFrom(msg.sender, address(this), amountToSend);\n _unwrapwrappedNativeTokenTo(payable(relayExecution.updatedRecipient), amountToSend);\n } else {\n if (!relayExecution.slowFill)\n IERC20Upgradeable(relayData.destinationToken).safeTransferFrom(\n msg.sender,\n relayExecution.updatedRecipient,\n amountToSend\n );\n else\n IERC20Upgradeable(relayData.destinationToken).safeTransfer(\n relayExecution.updatedRecipient,\n amountToSend\n );\n }\n }\n\n function _verifySlowFill(\n RelayExecution memory relayExecution,\n uint32 rootBundleId,\n bytes32[] memory proof\n ) internal view {\n SlowFill memory slowFill = SlowFill({\n relayData: relayExecution.relay,\n payoutAdjustmentPct: relayExecution.payoutAdjustmentPct\n });\n\n require(\n V2MerkleLib.verifySlowRelayFulfillment(rootBundles[rootBundleId].slowRelayRoot, slowFill, proof),\n \"Invalid slow relay proof\"\n );\n }\n\n function _emitFillRelay(RelayExecution memory relayExecution, uint256 fillAmountPreFees) internal {\n RelayExecutionInfo memory relayExecutionInfo = RelayExecutionInfo({\n relayerFeePct: relayExecution.updatedRelayerFeePct,\n recipient: relayExecution.updatedRecipient,\n message: relayExecution.updatedMessage,\n isSlowRelay: relayExecution.slowFill,\n payoutAdjustmentPct: relayExecution.payoutAdjustmentPct\n });\n\n emit FilledRelay(\n relayExecution.relay.amount,\n relayFills[relayExecution.relayHash],\n fillAmountPreFees,\n relayExecution.repaymentChainId,\n relayExecution.relay.originChainId,\n relayExecution.relay.destinationChainId,\n relayExecution.relay.relayerFeePct,\n relayExecution.relay.realizedLpFeePct,\n relayExecution.relay.depositId,\n relayExecution.relay.destinationToken,\n msg.sender,\n relayExecution.relay.depositor,\n relayExecution.relay.recipient,\n relayExecution.relay.message,\n relayExecutionInfo\n );\n }\n}\n" + }, + "contracts/test/MockSpokePoolV2.sol": { + "content": "//SPDX-License-Identifier: Unlicense\npragma solidity ^0.8.0;\n\nimport \"./MockSpokePool.sol\";\n\n/**\n * @title MockSpokePoolV2\n * @notice Upgrades MockSpokePool for no practical reason other than to demonstrate\n * upgradeability options\n */\ncontract MockSpokePoolV2 is MockSpokePool {\n event NewEvent(bool value);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _wrappedNativeTokenAddress) MockSpokePool(_wrappedNativeTokenAddress) {} // solhint-disable-line no-empty-blocks\n\n // Demonstrative of how we could reset state variables in a V2 contract conveniently while initializing new\n // modules. The `reinitializer` modifier is required to create new Initializable contracts.\n function reinitialize(address _hubPool) public reinitializer(2) {\n _setHubPool(_hubPool);\n }\n\n // Demonstrative new function we could add in a V2 contract.\n function emitEvent() external {\n emit NewEvent(true);\n }\n}\n" + }, + "contracts/test/PolygonERC20Test.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"@uma/core/contracts/common/implementation/ExpandedERC20.sol\";\nimport \"../PolygonTokenBridger.sol\";\n\n/**\n * @notice Simulated Polygon ERC20 for use in testing PolygonTokenBridger.\n */\ncontract PolygonERC20Test is ExpandedERC20 {\n constructor() ExpandedERC20(\"Polygon Test\", \"POLY_TEST\", 18) {} // solhint-disable-line no-empty-blocks\n\n function withdraw(uint256 amount) public {\n _burn(msg.sender, amount);\n }\n}\n" + }, + "contracts/test/PolygonMocks.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract RootChainManagerMock {\n function depositEtherFor(address user) external payable {} // solhint-disable-line no-empty-blocks\n\n function depositFor(\n address user,\n address rootToken,\n bytes calldata depositData\n ) external {} // solhint-disable-line no-empty-blocks\n}\n\ncontract FxStateSenderMock {\n // solhint-disable-next-line no-empty-blocks\n function sendMessageToChild(address _receiver, bytes calldata _data) external {}\n}\n\ncontract DepositManagerMock {\n function depositERC20ForUser(\n address token,\n address user,\n uint256 amount // solhint-disable-next-line no-empty-blocks\n ) external {} // solhint-disable-line no-empty-blocks\n}\n\ncontract PolygonRegistryMock {\n // solhint-disable-next-line no-empty-blocks\n function erc20Predicate() external returns (address predicate) {}\n}\n\ncontract PolygonERC20PredicateMock {\n // solhint-disable-next-line no-empty-blocks\n function startExitWithBurntTokens(bytes calldata data) external {}\n}\n\ncontract PolygonERC20Mock is ERC20 {\n // solhint-disable-next-line no-empty-blocks\n constructor() ERC20(\"Test ERC20\", \"TEST\") {}\n\n // solhint-disable-next-line no-empty-blocks\n function withdraw(uint256 amount) external {}\n}\n" + }, + "contracts/test/SuccinctMocks.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\ncontract TelepathyBroadcasterMock {\n function send(\n uint16,\n address,\n bytes calldata\n ) external pure returns (bytes32) {\n return bytes32(0);\n }\n}\n" + }, + "contracts/test/V2MerkleLib.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\";\nimport \"./interfaces/MockV2SpokePoolInterface.sol\";\n\n/**\n * @notice Library to help with merkle roots, proofs, and claims.\n */\nlibrary V2MerkleLib {\n function verifySlowRelayFulfillment(\n bytes32 root,\n MockV2SpokePoolInterface.SlowFill memory slowRelayFulfillment,\n bytes32[] memory proof\n ) internal pure returns (bool) {\n return MerkleProof.verify(proof, root, keccak256(abi.encode(slowRelayFulfillment)));\n }\n}\n" + }, + "contracts/upgradeable/AddressLibUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title AddressUpgradeable\n * @dev Collection of functions related to the address type\n * @notice Logic is 100% copied from \"@openzeppelin/contracts-upgradeable/contracts/utils/AddressUpgradeable.sol\" but one\n * comment is added to clarify why we allow delegatecall() in this contract, which is typically unsafe for use in\n * upgradeable implementation contracts.\n * @dev See https://docs.openzeppelin.com/upgrades-plugins/1.x/faq#delegatecall-selfdestruct for more details.\n * @custom:security-contact bugs@across.to\n */\nlibrary AddressLibUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n /// @custom:oz-upgrades-unsafe-allow delegatecall\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "contracts/upgradeable/EIP712CrossChainUpgradeable.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * This contract is based on OpenZeppelin's implementation:\n * https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/utils/cryptography/EIP712Upgradeable.sol\n *\n * NOTE: Modified version that allows to build a domain separator that relies on a different chain id than the chain this\n * contract is deployed to. An example use case we want to support is:\n * - User A signs a message on chain with id = 1\n * - User B executes a method by verifying user A's EIP-712 compliant signature on a chain with id != 1\n * @custom:security-contact bugs@across.to\n */\nabstract contract EIP712CrossChainUpgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId)\");\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal onlyInitializing {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator depending on the `originChainId`.\n * @param originChainId Chain id of network where message originates from.\n * @return bytes32 EIP-712-compliant domain separator.\n */\n function _domainSeparatorV4(uint256 originChainId) internal view returns (bytes32) {\n return keccak256(abi.encode(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION, originChainId));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 structHash = keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * ));\n * bytes32 digest = _hashTypedDataV4(structHash, originChainId);\n * address signer = ECDSA.recover(digest, signature);\n * ```\n * @param structHash Hashed struct as defined in https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct.\n * @param originChainId Chain id of network where message originates from.\n * @return bytes32 Hash digest that is recoverable via `EDCSA.recover`.\n */\n function _hashTypedDataV4(bytes32 structHash, uint256 originChainId) internal view virtual returns (bytes32) {\n return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(originChainId), structHash);\n }\n\n // Reserve storage slots for future versions of this base contract to add state variables without\n // affecting the storage layout of child contracts. Decrement the size of __gap whenever state variables\n // are added. This is at bottom of contract to make sure it's always at the end of storage.\n uint256[1000] private __gap;\n}\n" + }, + "contracts/upgradeable/MultiCallerUpgradeable.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @title MultiCallerUpgradeable\n * @notice Logic is 100% copied from \"@uma/core/contracts/common/implementation/MultiCaller.sol\" but one\n * comment is added to clarify why we allow delegatecall() in this contract, which is typically unsafe for use in\n * upgradeable implementation contracts.\n * @dev See https://docs.openzeppelin.com/upgrades-plugins/1.x/faq#delegatecall-selfdestruct for more details.\n * @custom:security-contact bugs@across.to\n */\ncontract MultiCallerUpgradeable {\n struct Result {\n bool success;\n bytes returnData;\n }\n\n function _validateMulticallData(bytes[] calldata data) internal virtual {\n // no-op\n }\n\n function multicall(bytes[] calldata data) external returns (bytes[] memory results) {\n _validateMulticallData(data);\n\n uint256 dataLength = data.length;\n results = new bytes[](dataLength);\n\n //slither-disable-start calls-loop\n for (uint256 i = 0; i < dataLength; ++i) {\n // Typically, implementation contracts used in the upgradeable proxy pattern shouldn't call `delegatecall`\n // because it could allow a malicious actor to call this implementation contract directly (rather than\n // through a proxy contract) and then selfdestruct() the contract, thereby freezing the upgradeable\n // proxy. However, since we're only delegatecall-ing into this contract, then we can consider this\n // use of delegatecall() safe.\n\n //slither-disable-start low-level-calls\n /// @custom:oz-upgrades-unsafe-allow delegatecall\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\n //slither-disable-end low-level-calls\n\n if (!success) {\n // Next 5 lines from https://ethereum.stackexchange.com/a/83577\n if (result.length < 68) revert();\n //slither-disable-next-line assembly\n assembly {\n result := add(result, 0x04)\n }\n revert(abi.decode(result, (string)));\n }\n\n results[i] = result;\n }\n //slither-disable-end calls-loop\n }\n\n function tryMulticall(bytes[] calldata data) external returns (Result[] memory results) {\n _validateMulticallData(data);\n\n uint256 dataLength = data.length;\n results = new Result[](dataLength);\n\n //slither-disable-start calls-loop\n for (uint256 i = 0; i < dataLength; ++i) {\n // The delegatecall here is safe for the same reasons outlined in the first multicall function.\n Result memory result = results[i];\n //slither-disable-start low-level-calls\n /// @custom:oz-upgrades-unsafe-allow delegatecall\n (result.success, result.returnData) = address(this).delegatecall(data[i]);\n //slither-disable-end low-level-calls\n }\n //slither-disable-end calls-loop\n }\n\n // Reserve storage slots for future versions of this base contract to add state variables without\n // affecting the storage layout of child contracts. Decrement the size of __gap whenever state variables\n // are added. This is at bottom of contract to make sure its always at the end of storage.\n uint256[1000] private __gap;\n}\n" + }, + "contracts/ZkSync_SpokePool.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport \"./SpokePool.sol\";\n\n// https://github.com/matter-labs/era-contracts/blob/6391c0d7bf6184d7f6718060e3991ba6f0efe4a7/zksync/contracts/bridge/L2ERC20Bridge.sol#L104\ninterface ZkBridgeLike {\n function withdraw(\n address _l1Receiver,\n address _l2Token,\n uint256 _amount\n ) external;\n}\n\ninterface IL2ETH {\n function withdraw(address _l1Receiver) external payable;\n}\n\n/**\n * @notice ZkSync specific SpokePool, intended to be compiled with `@matterlabs/hardhat-zksync-solc`.\n * @dev Resources for compiling and deploying contracts with hardhat: https://era.zksync.io/docs/tools/hardhat/hardhat-zksync-solc.html\n * @custom:security-contact bugs@across.to\n */\ncontract ZkSync_SpokePool is SpokePool {\n // On Ethereum, avoiding constructor parameters and putting them into constants reduces some of the gas cost\n // upon contract deployment. On zkSync the opposite is true: deploying the same bytecode for contracts,\n // while changing only constructor parameters can lead to substantial fee savings. So, the following params\n // are all set by passing in constructor params where possible.\n\n // ETH on ZkSync implements a subset of the ERC-20 interface, with additional built-in support to bridge to L1.\n address public l2Eth;\n\n // Bridge used to withdraw ERC20's to L1\n ZkBridgeLike public zkErc20Bridge;\n\n event SetZkBridge(address indexed erc20Bridge, address indexed oldErc20Bridge);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeTokenAddress,\n uint32 _depositQuoteTimeBuffer,\n uint32 _fillDeadlineBuffer\n ) SpokePool(_wrappedNativeTokenAddress, _depositQuoteTimeBuffer, _fillDeadlineBuffer) {} // solhint-disable-line no-empty-blocks\n\n /**\n * @notice Construct the ZkSync SpokePool.\n * @param _initialDepositId Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate\n * relay hash collisions.\n * @param _zkErc20Bridge Address of L2 ERC20 gateway. Can be reset by admin.\n * @param _crossDomainAdmin Cross domain admin to set. Can be changed by admin.\n * @param _hubPool Hub pool address to set. Can be changed by admin.\n */\n function initialize(\n uint32 _initialDepositId,\n ZkBridgeLike _zkErc20Bridge,\n address _crossDomainAdmin,\n address _hubPool\n ) public initializer {\n l2Eth = 0x000000000000000000000000000000000000800A;\n __SpokePool_init(_initialDepositId, _crossDomainAdmin, _hubPool);\n _setZkBridge(_zkErc20Bridge);\n }\n\n modifier onlyFromCrossDomainAdmin() {\n require(msg.sender == _applyL1ToL2Alias(crossDomainAdmin), \"ONLY_COUNTERPART_GATEWAY\");\n _;\n }\n\n /********************************************************\n * ZKSYNC-SPECIFIC CROSS-CHAIN ADMIN FUNCTIONS *\n ********************************************************/\n\n /**\n * @notice Change L2 token bridge addresses. Callable only by admin.\n * @param _zkErc20Bridge New address of L2 ERC20 gateway.\n */\n function setZkBridge(ZkBridgeLike _zkErc20Bridge) public onlyAdmin nonReentrant {\n _setZkBridge(_zkErc20Bridge);\n }\n\n /**************************************\n * INTERNAL FUNCTIONS *\n **************************************/\n\n /**\n * @notice Wraps any ETH into WETH before executing base function. This is necessary because SpokePool receives\n * ETH over the canonical token bridge instead of WETH.\n */\n function _preExecuteLeafHook(address l2TokenAddress) internal override {\n if (l2TokenAddress == address(wrappedNativeToken)) _depositEthToWeth();\n }\n\n // Wrap any ETH owned by this contract so we can send expected L2 token to recipient. This is necessary because\n // this SpokePool will receive ETH from the canonical token bridge instead of WETH. This may not be neccessary\n // if ETH on ZkSync is treated as ETH and the fallback() function is triggered when this contract receives\n // ETH. We will have to test this but this function for now allows the contract to safely convert all of its\n // held ETH into WETH at the cost of higher gas costs.\n function _depositEthToWeth() internal {\n //slither-disable-next-line arbitrary-send-eth\n if (address(this).balance > 0) wrappedNativeToken.deposit{ value: address(this).balance }();\n }\n\n function _bridgeTokensToHubPool(uint256 amountToReturn, address l2TokenAddress) internal override {\n // SpokePool is expected to receive ETH from the L1 HubPool and currently, withdrawing ETH directly\n // over the ERC20 Bridge is blocked at the contract level. Therefore, we need to unwrap it before withdrawing.\n if (l2TokenAddress == address(wrappedNativeToken)) {\n WETH9Interface(l2TokenAddress).withdraw(amountToReturn); // Unwrap into ETH.\n // To withdraw tokens, we actually call 'withdraw' on the L2 eth token itself.\n IL2ETH(l2Eth).withdraw{ value: amountToReturn }(hubPool);\n } else {\n zkErc20Bridge.withdraw(hubPool, l2TokenAddress, amountToReturn);\n }\n }\n\n function _setZkBridge(ZkBridgeLike _zkErc20Bridge) internal {\n address oldErc20Bridge = address(zkErc20Bridge);\n zkErc20Bridge = _zkErc20Bridge;\n emit SetZkBridge(address(_zkErc20Bridge), oldErc20Bridge);\n }\n\n // L1 addresses are transformed during l1->l2 calls.\n // See https://github.com/matter-labs/era-contracts/blob/main/docs/Overview.md#mailboxfacet for more information.\n // Another source: https://github.com/matter-labs/era-contracts/blob/41c25aa16d182f757c3fed1463c78a81896f65e6/ethereum/contracts/vendor/AddressAliasHelper.sol#L28\n function _applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n unchecked {\n l2Address = address(uint160(l1Address) + uint160(0x1111000000000000000000000000000000001111));\n }\n }\n\n function _requireAdminSender() internal override onlyFromCrossDomainAdmin {}\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 + } + } +} diff --git a/deployments/zora/Zora_SpokePool.json b/deployments/zora/Zora_SpokePool.json index b9d34405a..9660e9929 100644 --- a/deployments/zora/Zora_SpokePool.json +++ b/deployments/zora/Zora_SpokePool.json @@ -1,5 +1,5 @@ { - "address": "0xeF684C38F94F48775959ECf2012D7E864ffb9dd4", + "address": "0x13fDac9F9b4777705db45291bbFF3c972c6d1d97", "abi": [ { "inputs": [ @@ -2494,7 +2494,7 @@ "type": "receive" } ], - "numDeployments": 1, + "numDeployments": 4, "solcInputHash": "5c69757f9ebaa3d282fd65ee8c5c53a7", "metadata": "{\"compiler\":{\"version\":\"0.8.23+commit.f704f362\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_wrappedNativeTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"_depositQuoteTimeBuffer\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_fillDeadlineBuffer\",\"type\":\"uint32\"},{\"internalType\":\"contract IERC20\",\"name\":\"_l2Usdc\",\"type\":\"address\"},{\"internalType\":\"contract ITokenMessenger\",\"name\":\"_cctpTokenMessenger\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ClaimedMerkleLeaf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DepositsArePaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DisabledRoute\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExpiredFillDeadline\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FillsArePaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidChainId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCrossDomainAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDepositorSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExclusiveRelayer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExclusivityDeadline\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFillDeadline\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidHubPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMerkleLeaf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidMerkleProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayoutAdjustmentPct\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidQuoteTimestamp\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRelayerFeePct\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSlowFillRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MaxTransferSizeExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MsgValueDoesNotMatchInputAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSlowFillsInExclusivityWindow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotCrossChainCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotCrossDomainAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotEOA\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotExclusiveRelayer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RelayFilled\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"rootBundleId\",\"type\":\"uint256\"}],\"name\":\"EmergencyDeleteRootBundle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"name\":\"EnabledDepositRoute\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountToReturn\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"refundAmounts\",\"type\":\"uint256[]\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"rootBundleId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"leafId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"l2TokenAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"refundAddresses\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"ExecutedRelayerRefundRoot\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalFilledAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fillAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repaymentChainId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"originChainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"int64\",\"name\":\"relayerFeePct\",\"type\":\"int64\"},{\"indexed\":false,\"internalType\":\"int64\",\"name\":\"realizedLpFeePct\",\"type\":\"int64\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"depositId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destinationToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"int64\",\"name\":\"relayerFeePct\",\"type\":\"int64\"},{\"internalType\":\"bool\",\"name\":\"isSlowRelay\",\"type\":\"bool\"},{\"internalType\":\"int256\",\"name\":\"payoutAdjustmentPct\",\"type\":\"int256\"}],\"indexed\":false,\"internalType\":\"struct SpokePool.RelayExecutionInfo\",\"name\":\"updatableRelayData\",\"type\":\"tuple\"}],\"name\":\"FilledRelay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"inputToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"outputToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"inputAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repaymentChainId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"originChainId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"depositId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"fillDeadline\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"exclusivityDeadline\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"exclusiveRelayer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"updatedRecipient\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"updatedMessage\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"updatedOutputAmount\",\"type\":\"uint256\"},{\"internalType\":\"enum V3SpokePoolInterface.FillType\",\"name\":\"fillType\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"struct V3SpokePoolInterface.V3RelayExecutionEventInfo\",\"name\":\"relayExecutionInfo\",\"type\":\"tuple\"}],\"name\":\"FilledV3Relay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"originChainId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"int64\",\"name\":\"relayerFeePct\",\"type\":\"int64\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"depositId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"quoteTimestamp\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"FundsDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isPaused\",\"type\":\"bool\"}],\"name\":\"PausedDeposits\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isPaused\",\"type\":\"bool\"}],\"name\":\"PausedFills\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"rootBundleId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"relayerRefundRoot\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"slowRelayRoot\",\"type\":\"bytes32\"}],\"name\":\"RelayedRootBundle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"int64\",\"name\":\"newRelayerFeePct\",\"type\":\"int64\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"depositId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"updatedRecipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"updatedMessage\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"depositorSignature\",\"type\":\"bytes\"}],\"name\":\"RequestedSpeedUpDeposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"updatedOutputAmount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"depositId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"updatedRecipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"updatedMessage\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"depositorSignature\",\"type\":\"bytes\"}],\"name\":\"RequestedSpeedUpV3Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"inputToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"outputToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"inputAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"originChainId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"depositId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"fillDeadline\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"exclusivityDeadline\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"exclusiveRelayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"RequestedV3SlowFill\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newHubPool\",\"type\":\"address\"}],\"name\":\"SetHubPool\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"newL1Gas\",\"type\":\"uint32\"}],\"name\":\"SetL1Gas\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenBridge\",\"type\":\"address\"}],\"name\":\"SetL2TokenBridge\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\"}],\"name\":\"SetRemoteL1Token\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"SetXDomainAdmin\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountToReturn\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"leafId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l2TokenAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"TokensBridged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"inputToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"outputToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"inputAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"depositId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"quoteTimestamp\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"fillDeadline\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"exclusivityDeadline\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"exclusiveRelayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"V3FundsDeposited\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"EMPTY_RELAYER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"EMPTY_REPAYMENT_CHAIN_ID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INFINITE_FILL_DEADLINE\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_TRANSFER_SIZE\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MESSENGER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"UPDATE_V3_DEPOSIT_DETAILS_HASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_initialDepositId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"_crossDomainAdmin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_hubPool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Eth\",\"type\":\"address\"}],\"name\":\"__OvmSpokePool_init\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_initialDepositId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"_crossDomainAdmin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_hubPool\",\"type\":\"address\"}],\"name\":\"__SpokePool_init\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cctpTokenMessenger\",\"outputs\":[{\"internalType\":\"contract ITokenMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"chainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"crossDomainAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"int64\",\"name\":\"relayerFeePct\",\"type\":\"int64\"},{\"internalType\":\"uint32\",\"name\":\"quoteTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"inputToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"outputToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"inputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"exclusiveRelayer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"quoteTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fillDeadline\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"exclusivityDeadlineOffset\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"depositExclusive\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"int64\",\"name\":\"relayerFeePct\",\"type\":\"int64\"},{\"internalType\":\"uint32\",\"name\":\"quoteTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"depositFor\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositQuoteTimeBuffer\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"inputToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"outputToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"inputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"exclusiveRelayer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"quoteTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fillDeadline\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"exclusivityDeadline\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"depositV3\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"inputToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"outputToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"inputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"exclusiveRelayer\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"fillDeadlineOffset\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"exclusivityDeadline\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"depositV3Now\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"rootBundleId\",\"type\":\"uint256\"}],\"name\":\"emergencyDeleteRootBundle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"enabledDepositRoutes\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"rootBundleId\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amountToReturn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"refundAmounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint32\",\"name\":\"leafId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"l2TokenAddress\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"refundAddresses\",\"type\":\"address[]\"}],\"internalType\":\"struct SpokePoolInterface.RelayerRefundLeaf\",\"name\":\"relayerRefundLeaf\",\"type\":\"tuple\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"executeRelayerRefundLeaf\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"exclusiveRelayer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"inputToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"outputToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"inputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"depositId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fillDeadline\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"exclusivityDeadline\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"internalType\":\"struct V3SpokePoolInterface.V3RelayData\",\"name\":\"relayData\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedOutputAmount\",\"type\":\"uint256\"}],\"internalType\":\"struct V3SpokePoolInterface.V3SlowFill\",\"name\":\"slowFillLeaf\",\"type\":\"tuple\"},{\"internalType\":\"uint32\",\"name\":\"rootBundleId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"executeV3SlowRelayLeaf\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fillDeadlineBuffer\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"fillStatuses\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"exclusiveRelayer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"inputToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"outputToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"inputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"depositId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fillDeadline\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"exclusivityDeadline\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"internalType\":\"struct V3SpokePoolInterface.V3RelayData\",\"name\":\"relayData\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"repaymentChainId\",\"type\":\"uint256\"}],\"name\":\"fillV3Relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"exclusiveRelayer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"inputToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"outputToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"inputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"depositId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fillDeadline\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"exclusivityDeadline\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"internalType\":\"struct V3SpokePoolInterface.V3RelayData\",\"name\":\"relayData\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"repaymentChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"updatedOutputAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"updatedRecipient\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"updatedMessage\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"depositorSignature\",\"type\":\"bytes\"}],\"name\":\"fillV3RelayWithUpdatedDeposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"hubPool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_initialDepositId\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"_crossDomainAdmin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_hubPool\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1Gas\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Eth\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"multicall\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"results\",\"type\":\"bytes[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"numberOfDeposits\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"pause\",\"type\":\"bool\"}],\"name\":\"pauseDeposits\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"pause\",\"type\":\"bool\"}],\"name\":\"pauseFills\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pausedDeposits\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pausedFills\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"proxiableUUID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"recipientCircleDomainId\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"relayerRefundRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"slowRelayRoot\",\"type\":\"bytes32\"}],\"name\":\"relayRootBundle\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"remoteL1Tokens\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"exclusiveRelayer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"inputToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"outputToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"inputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"originChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"depositId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fillDeadline\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"exclusivityDeadline\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"internalType\":\"struct V3SpokePoolInterface.V3RelayData\",\"name\":\"relayData\",\"type\":\"tuple\"}],\"name\":\"requestV3SlowFill\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"rootBundles\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"slowRelayRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"relayerRefundRoot\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newCrossDomainAdmin\",\"type\":\"address\"}],\"name\":\"setCrossDomainAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"originToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"}],\"name\":\"setEnableRoute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newHubPool\",\"type\":\"address\"}],\"name\":\"setHubPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"newl1Gas\",\"type\":\"uint32\"}],\"name\":\"setL1GasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"l1Token\",\"type\":\"address\"}],\"name\":\"setRemoteL1Token\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"l2Token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenBridge\",\"type\":\"address\"}],\"name\":\"setTokenBridge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"depositId\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"updatedOutputAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"updatedRecipient\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"updatedMessage\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"depositorSignature\",\"type\":\"bytes\"}],\"name\":\"speedUpV3Deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"tokenBridges\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"data\",\"type\":\"bytes[]\"}],\"name\":\"tryMulticall\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"internalType\":\"struct MultiCallerUpgradeable.Result[]\",\"name\":\"results\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usdcToken\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"wrappedNativeToken\",\"outputs\":[{\"internalType\":\"contract WETH9Interface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"custom:security-contact\":\"bugs@across.to\",\"events\":{\"AdminChanged(address,address)\":{\"details\":\"Emitted when the admin account has changed.\"},\"BeaconUpgraded(address)\":{\"details\":\"Emitted when the beacon is changed.\"},\"FilledRelay(uint256,uint256,uint256,uint256,uint256,uint256,int64,int64,uint32,address,address,address,address,bytes,(address,bytes,int64,bool,int256))\":{\"custom:audit\":\"FOLLOWING EVENT TO BE DEPRECATED\"},\"FundsDeposited(uint256,uint256,uint256,int64,uint32,uint32,address,address,address,bytes)\":{\"custom:audit\":\"FOLLOWING EVENT TO BE DEPRECATED\"},\"Initialized(uint8)\":{\"details\":\"Triggered when the contract has been initialized or reinitialized.\"},\"RequestedSpeedUpDeposit(int64,uint32,address,address,bytes,bytes)\":{\"custom:audit\":\"FOLLOWING EVENT TO BE DEPRECATED\"},\"Upgraded(address)\":{\"details\":\"Emitted when the implementation is upgraded.\"}},\"kind\":\"dev\",\"methods\":{\"__OvmSpokePool_init(uint32,address,address,address)\":{\"params\":{\"_crossDomainAdmin\":\"Cross domain admin to set. Can be changed by admin.\",\"_hubPool\":\"Hub pool address to set. Can be changed by admin.\",\"_initialDepositId\":\"Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate relay hash collisions.\",\"_l2Eth\":\"Address of L2 ETH token. Usually should be Lib_PreeployAddresses.OVM_ETH but sometimes this can be different, like with Boba which flips the WETH and OVM_ETH addresses.\"}},\"__SpokePool_init(uint32,address,address)\":{\"params\":{\"_crossDomainAdmin\":\"Cross domain admin to set. Can be changed by admin.\",\"_hubPool\":\"Hub pool address to set. Can be changed by admin.\",\"_initialDepositId\":\"Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate relay hash collisions.\"}},\"chainId()\":{\"details\":\"Some L2s like ZKSync don't support the CHAIN_ID opcode so we allow the implementer to override this.\"},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\"},\"deposit(address,address,uint256,uint256,int64,uint32,bytes,uint256)\":{\"details\":\"Produces a V3FundsDeposited event with an infinite expiry, meaning that this deposit can never expire. Moreover, the event's outputToken is set to 0x0 meaning that this deposit can always be slow filled.\",\"params\":{\"amount\":\"Amount of tokens to deposit. Will be amount of tokens to receive less fees.\",\"destinationChainId\":\"Denotes network where user will receive funds from SpokePool by a relayer.\",\"message\":\"Arbitrary data that can be used to pass additional information to the recipient along with the tokens. Note: this is intended to be used to pass along instructions for how a contract should use or allocate the tokens.\",\"originToken\":\"Token to lock into this contract to initiate deposit.\",\"quoteTimestamp\":\"Timestamp used by relayers to compute this deposit's realizedLPFeePct which is paid to LP pool on HubPool.\",\"recipient\":\"Address to receive funds at on destination chain.\",\"relayerFeePct\":\"% of deposit amount taken out to incentivize a fast relayer.\"}},\"depositExclusive(address,address,address,address,uint256,uint256,uint256,address,uint32,uint32,uint32,bytes)\":{\"params\":{\"depositor\":\"The account credited with the deposit who can request to \\\"speed up\\\" this deposit by modifying the output amount, recipient, and message.\",\"destinationChainId\":\"The destination chain identifier. Must be enabled along with the input token as a valid deposit route from this spoke pool or this transaction will revert.\",\"exclusiveRelayer\":\"The relayer that will be exclusively allowed to fill this deposit before the exclusivity deadline timestamp.\",\"exclusivityDeadlineOffset\":\"Added to the current time to set the exclusive reayer deadline, which is the deadline for the exclusiveRelayer to fill the deposit. After this destination chain timestamp, anyone can fill the deposit.\",\"fillDeadline\":\"The deadline for the relayer to fill the deposit. After this destination chain timestamp, the fill will revert on the destination chain. Must be set between [currentTime, currentTime + fillDeadlineBuffer] where currentTime is block.timestamp on this chain or this transaction will revert.\",\"inputAmount\":\"The amount of input tokens to pull from the caller's account and lock into this contract. This amount will be sent to the relayer on their repayment chain of choice as a refund following an optimistic challenge window in the HubPool, plus a system fee.\",\"inputToken\":\"The token pulled from the caller's account and locked into this contract to initiate the deposit. The equivalent of this token on the relayer's repayment chain of choice will be sent as a refund. If this is equal to the wrapped native token then the caller can optionally pass in native token as msg.value, as long as msg.value = inputTokenAmount.\",\"message\":\"The message to send to the recipient on the destination chain if the recipient is a contract. If the message is not empty, the recipient contract must implement handleV3AcrossMessage() or the fill will revert.\",\"outputAmount\":\"The amount of output tokens that the relayer will send to the recipient on the destination.\",\"outputToken\":\"The token that the relayer will send to the recipient on the destination chain. Must be an ERC20.\",\"quoteTimestamp\":\"The HubPool timestamp that is used to determine the system fee paid by the depositor. This must be set to some time between [currentTime - depositQuoteTimeBuffer, currentTime] where currentTime is block.timestamp on this chain or this transaction will revert.\",\"recipient\":\"The account receiving funds on the destination chain. Can be an EOA or a contract. If the output token is the wrapped native token for the chain, then the recipient will receive native token if an EOA or wrapped native token if a contract.\"}},\"depositFor(address,address,address,uint256,uint256,int64,uint32,bytes,uint256)\":{\"params\":{\"amount\":\"Amount of tokens to deposit. Will be amount of tokens to receive less fees.\",\"depositor\":\"Address who is credited for depositing funds on origin chain and can speed up the deposit.\",\"destinationChainId\":\"Denotes network where user will receive funds from SpokePool by a relayer.\",\"message\":\"Arbitrary data that can be used to pass additional information to the recipient along with the tokens. Note: this is intended to be used to pass along instructions for how a contract should use or allocate the tokens.\",\"originToken\":\"Token to lock into this contract to initiate deposit.\",\"quoteTimestamp\":\"Timestamp used by relayers to compute this deposit's realizedLPFeePct which is paid to LP pool on HubPool.\",\"recipient\":\"Address to receive funds at on destination chain.\",\"relayerFeePct\":\"% of deposit amount taken out to incentivize a fast relayer.\"}},\"depositV3(address,address,address,address,uint256,uint256,uint256,address,uint32,uint32,uint32,bytes)\":{\"details\":\"On the destination chain, the hash of the deposit data will be used to uniquely identify this deposit, so modifying any params in it will result in a different hash and a different deposit. The hash will comprise all parameters to this function along with this chain's chainId(). Relayers are only refunded for filling deposits with deposit hashes that map exactly to the one emitted by this contract.\",\"params\":{\"depositor\":\"The account credited with the deposit who can request to \\\"speed up\\\" this deposit by modifying the output amount, recipient, and message.\",\"destinationChainId\":\"The destination chain identifier. Must be enabled along with the input token as a valid deposit route from this spoke pool or this transaction will revert.\",\"exclusiveRelayer\":\"The relayer that will be exclusively allowed to fill this deposit before the exclusivity deadline timestamp. This must be a valid, non-zero address if the exclusivity deadline is greater than the current block.timestamp. If the exclusivity deadline is < currentTime, then this must be address(0), and vice versa if this is address(0).\",\"exclusivityDeadline\":\"The deadline for the exclusive relayer to fill the deposit. After this destination chain timestamp, anyone can fill this deposit on the destination chain. If exclusiveRelayer is set to address(0), then this also must be set to 0, (and vice versa), otherwise this must be set >= current time.\",\"fillDeadline\":\"The deadline for the relayer to fill the deposit. After this destination chain timestamp, the fill will revert on the destination chain. Must be set between [currentTime, currentTime + fillDeadlineBuffer] where currentTime is block.timestamp on this chain or this transaction will revert.\",\"inputAmount\":\"The amount of input tokens to pull from the caller's account and lock into this contract. This amount will be sent to the relayer on their repayment chain of choice as a refund following an optimistic challenge window in the HubPool, less a system fee.\",\"inputToken\":\"The token pulled from the caller's account and locked into this contract to initiate the deposit. The equivalent of this token on the relayer's repayment chain of choice will be sent as a refund. If this is equal to the wrapped native token then the caller can optionally pass in native token as msg.value, as long as msg.value = inputTokenAmount.\",\"message\":\"The message to send to the recipient on the destination chain if the recipient is a contract. If the message is not empty, the recipient contract must implement handleV3AcrossMessage() or the fill will revert.\",\"outputAmount\":\"The amount of output tokens that the relayer will send to the recipient on the destination.\",\"outputToken\":\"The token that the relayer will send to the recipient on the destination chain. Must be an ERC20.\",\"quoteTimestamp\":\"The HubPool timestamp that is used to determine the system fee paid by the depositor. This must be set to some time between [currentTime - depositQuoteTimeBuffer, currentTime] where currentTime is block.timestamp on this chain or this transaction will revert.\",\"recipient\":\"The account receiving funds on the destination chain. Can be an EOA or a contract. If the output token is the wrapped native token for the chain, then the recipient will receive native token if an EOA or wrapped native token if a contract.\"}},\"depositV3Now(address,address,address,address,uint256,uint256,uint256,address,uint32,uint32,bytes)\":{\"params\":{\"depositor\":\"The account credited with the deposit who can request to \\\"speed up\\\" this deposit by modifying the output amount, recipient, and message.\",\"destinationChainId\":\"The destination chain identifier. Must be enabled along with the input token as a valid deposit route from this spoke pool or this transaction will revert.\",\"exclusiveRelayer\":\"The relayer that will be exclusively allowed to fill this deposit before the exclusivity deadline timestamp.\",\"exclusivityDeadline\":\"The latest timestamp that only the exclusive relayer can fill the deposit. After this destination chain timestamp, anyone can fill this deposit on the destination chain. Should be 0 if exclusive relayer is 0.\",\"fillDeadlineOffset\":\"Added to the current time to set the fill deadline, which is the deadline for the relayer to fill the deposit. After this destination chain timestamp, the fill will revert on the destination chain.\",\"inputAmount\":\"The amount of input tokens to pull from the caller's account and lock into this contract. This amount will be sent to the relayer on their repayment chain of choice as a refund following an optimistic challenge window in the HubPool, plus a system fee.\",\"inputToken\":\"The token pulled from the caller's account and locked into this contract to initiate the deposit. The equivalent of this token on the relayer's repayment chain of choice will be sent as a refund. If this is equal to the wrapped native token then the caller can optionally pass in native token as msg.value, as long as msg.value = inputTokenAmount.\",\"message\":\"The message to send to the recipient on the destination chain if the recipient is a contract. If the message is not empty, the recipient contract must implement handleV3AcrossMessage() or the fill will revert.\",\"outputAmount\":\"The amount of output tokens that the relayer will send to the recipient on the destination.\",\"outputToken\":\"The token that the relayer will send to the recipient on the destination chain. Must be an ERC20.\",\"recipient\":\"The account receiving funds on the destination chain. Can be an EOA or a contract. If the output token is the wrapped native token for the chain, then the recipient will receive native token if an EOA or wrapped native token if a contract.\"}},\"emergencyDeleteRootBundle(uint256)\":{\"params\":{\"rootBundleId\":\"Index of the root bundle that needs to be deleted. Note: this is intentionally a uint256 to ensure that a small input range doesn't limit which indices this method is able to reach.\"}},\"executeRelayerRefundLeaf(uint32,(uint256,uint256,uint256[],uint32,address,address[]),bytes32[])\":{\"params\":{\"proof\":\"Inclusion proof for this leaf in relayer refund root in root bundle.\",\"relayerRefundLeaf\":\"Contains all data necessary to reconstruct leaf contained in root bundle and to refund relayer. This data structure is explained in detail in the SpokePoolInterface.\",\"rootBundleId\":\"Unique ID of root bundle containing relayer refund root that this leaf is contained in.\"}},\"executeV3SlowRelayLeaf(((address,address,address,address,address,uint256,uint256,uint256,uint32,uint32,uint32,bytes),uint256,uint256),uint32,bytes32[])\":{\"details\":\"Executing a slow fill leaf is equivalent to filling the relayData so this function cannot be used to double fill a recipient. The relayData that is filled is included in the slowFillLeaf and is hashed like any other fill sent through fillV3Relay().There is no relayer credited with filling this relay since funds are sent directly out of this contract.\",\"params\":{\"proof\":\"Inclusion proof for this leaf in slow relay root in root bundle.\",\"rootBundleId\":\"Unique ID of root bundle containing slow relay root that this leaf is contained in.\",\"slowFillLeaf\":\"Contains all data necessary to uniquely identify a relay for this chain. This struct is hashed and included in a merkle root that is relayed to all spoke pools. - relayData: struct containing all the data needed to identify the original deposit to be slow filled. - chainId: chain identifier where slow fill leaf should be executed. If this doesn't match this chain's chainId, then this function will revert. - updatedOutputAmount: Amount to be sent to recipient out of this contract's balance. Can be set differently from relayData.outputAmount to charge a different fee because this deposit was \\\"slow\\\" filled. Usually, this will be set higher to reimburse the recipient for waiting for the slow fill.\"}},\"fillV3Relay((address,address,address,address,address,uint256,uint256,uint256,uint32,uint32,uint32,bytes),uint256)\":{\"details\":\"The fee paid to relayers and the system should be captured in the spread between output amount and input amount when adjusted to be denominated in the input token. A relayer on the destination chain will send outputAmount of outputTokens to the recipient and receive inputTokens on a repayment chain of their choice. Therefore, the fee should account for destination fee transaction costs, the relayer's opportunity cost of capital while they wait to be refunded following an optimistic challenge window in the HubPool, and a system fee charged to relayers.The hash of the relayData will be used to uniquely identify the deposit to fill, so modifying any params in it will result in a different hash and a different deposit. The hash will comprise all parameters passed to depositV3() on the origin chain along with that chain's chainId(). This chain's chainId() must therefore match the destinationChainId passed into depositV3. Relayers are only refunded for filling deposits with deposit hashes that map exactly to the one emitted by the origin SpokePool therefore the relayer should not modify any params in relayData.Cannot fill more than once. Partial fills are not supported.\",\"params\":{\"relayData\":\"struct containing all the data needed to identify the deposit to be filled. Should match all the same-named parameters emitted in the origin chain V3FundsDeposited event. - depositor: The account credited with the deposit who can request to \\\"speed up\\\" this deposit by modifying the output amount, recipient, and message. - recipient The account receiving funds on this chain. Can be an EOA or a contract. If the output token is the wrapped native token for the chain, then the recipient will receive native token if an EOA or wrapped native token if a contract. - inputToken: The token pulled from the caller's account to initiate the deposit. The equivalent of this token on the repayment chain will be sent as a refund to the caller. - outputToken The token that the caller will send to the recipient on the destination chain. Must be an ERC20. - inputAmount: This amount, less a system fee, will be sent to the caller on their repayment chain of choice as a refund following an optimistic challenge window in the HubPool. - outputAmount: The amount of output tokens that the caller will send to the recipient. - originChainId: The origin chain identifier. - exclusiveRelayer The relayer that will be exclusively allowed to fill this deposit before the exclusivity deadline timestamp. - fillDeadline The deadline for the caller to fill the deposit. After this timestamp, the fill will revert on the destination chain. - exclusivityDeadline: The deadline for the exclusive relayer to fill the deposit. After this timestamp, anyone can fill this deposit. - message The message to send to the recipient if the recipient is a contract that implements a handleV3AcrossMessage() public function\",\"repaymentChainId\":\"Chain of SpokePool where relayer wants to be refunded after the challenge window has passed. Will receive inputAmount of the equivalent token to inputToken on the repayment chain.\"}},\"fillV3RelayWithUpdatedDeposit((address,address,address,address,address,uint256,uint256,uint256,uint32,uint32,uint32,bytes),uint256,uint256,address,bytes,bytes)\":{\"details\":\"Subject to same exclusivity deadline rules as fillV3Relay().\",\"params\":{\"depositorSignature\":\"Signed EIP712 hashstruct containing the deposit ID. Should be signed by the depositor account.\",\"relayData\":\"struct containing all the data needed to identify the deposit to be filled. See fillV3Relay().\",\"repaymentChainId\":\"Chain of SpokePool where relayer wants to be refunded after the challenge window has passed. See fillV3Relay().\",\"updatedMessage\":\"New message to use for this deposit.\",\"updatedOutputAmount\":\"New output amount to use for this deposit.\",\"updatedRecipient\":\"New recipient to use for this deposit.\"}},\"getCurrentTime()\":{\"returns\":{\"_0\":\"uint for the current timestamp.\"}},\"initialize(uint32,address,address)\":{\"params\":{\"_crossDomainAdmin\":\"Cross domain admin to set. Can be changed by admin.\",\"_hubPool\":\"Hub pool address to set. Can be changed by admin.\",\"_initialDepositId\":\"Starting deposit ID. Set to 0 unless this is a re-deployment in order to mitigate relay hash collisions.\"}},\"pauseDeposits(bool)\":{\"details\":\"Affects `deposit()` but not `speedUpDeposit()`, so that existing deposits can be sped up and still relayed.\",\"params\":{\"pause\":\"true if the call is meant to pause the system, false if the call is meant to unpause it.\"}},\"pauseFills(bool)\":{\"details\":\"Affects fillRelayWithUpdatedDeposit() and fillRelay().\",\"params\":{\"pause\":\"true if the call is meant to pause the system, false if the call is meant to unpause it.\"}},\"proxiableUUID()\":{\"details\":\"Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the implementation. It is used to validate the implementation's compatibility when performing an upgrade. IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\"},\"relayRootBundle(bytes32,bytes32)\":{\"params\":{\"relayerRefundRoot\":\"Merkle root containing relayer refund leaves that can be individually executed via executeRelayerRefundLeaf().\",\"slowRelayRoot\":\"Merkle root containing slow relay fulfillment leaves that can be individually executed via executeSlowRelayLeaf().\"}},\"requestV3SlowFill((address,address,address,address,address,uint256,uint256,uint256,uint32,uint32,uint32,bytes))\":{\"details\":\"Slow fills are not possible unless the input and output tokens are \\\"equivalent\\\", i.e. they route to the same L1 token via PoolRebalanceRoutes.Slow fills are created by inserting slow fill objects into a merkle tree that is included in the next HubPool \\\"root bundle\\\". Once the optimistic challenge window has passed, the HubPool will relay the slow root to this chain via relayRootBundle(). Once the slow root is relayed, the slow fill can be executed by anyone who calls executeV3SlowRelayLeaf().Cannot request a slow fill if the fill deadline has passed.Cannot request a slow fill if the relay has already been filled or a slow fill has already been requested.\",\"params\":{\"relayData\":\"struct containing all the data needed to identify the deposit that should be slow filled. If any of the params are missing or different from the origin chain deposit, then Across will not include a slow fill for the intended deposit.\"}},\"setCrossDomainAdmin(address)\":{\"params\":{\"newCrossDomainAdmin\":\"New cross domain admin.\"}},\"setEnableRoute(address,uint256,bool)\":{\"params\":{\"destinationChainId\":\"Chain ID for where depositor wants to receive funds.\",\"enabled\":\"True to enable deposits, False otherwise.\",\"originToken\":\"Token that depositor can deposit to this contract.\"}},\"setHubPool(address)\":{\"params\":{\"newHubPool\":\"New hub pool.\"}},\"setL1GasLimit(uint32)\":{\"params\":{\"newl1Gas\":\"New L1 gas limit to set.\"}},\"setTokenBridge(address,address)\":{\"details\":\"If this mapping isn't set for an L2 token, then the standard bridge will be used to bridge this token.\",\"params\":{\"tokenBridge\":\"Address of token bridge\"}},\"speedUpV3Deposit(address,uint32,uint256,address,bytes,bytes)\":{\"details\":\"the depositor and depositId must match the params in a V3FundsDeposited event that the depositor wants to speed up. The relayer has the option but not the obligation to use this updated information when filling the deposit via fillV3RelayWithUpdatedDeposit().\",\"params\":{\"depositId\":\"Deposit ID to speed up.\",\"depositor\":\"Depositor that must sign the depositorSignature and was the original depositor.\",\"depositorSignature\":\"Signed EIP712 hashstruct containing the deposit ID. Should be signed by the depositor account. If depositor is a contract, then should implement EIP1271 to sign as a contract. See _verifyUpdateV3DepositMessage() for more details about how this signature should be constructed.\",\"updatedMessage\":\"New message to use for this deposit. Can be modified if the recipient is a contract that expects to receive a message from the relay and for some reason needs to be modified.\",\"updatedOutputAmount\":\"New output amount to use for this deposit. Should be lower than previous value otherwise relayer has no incentive to use this updated value.\",\"updatedRecipient\":\"New recipient to use for this deposit. Can be modified if the recipient is a contract that expects to receive a message from the relay and for some reason needs to be modified.\"}},\"upgradeTo(address)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"},\"upgradeToAndCall(address,bytes)\":{\"custom:oz-upgrades-unsafe-allow-reachable\":\"delegatecall\",\"details\":\"Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call encoded in `data`. Calls {_authorizeUpgrade}. Emits an {Upgraded} event.\"}},\"version\":1},\"userdoc\":{\"events\":{\"FundsDeposited(uint256,uint256,uint256,int64,uint32,uint32,address,address,address,bytes)\":{\"notice\":\"EVENTS BELOW ARE DEPRECATED AND EXIST FOR BACKWARDS COMPATIBILITY ONLY.\"}},\"kind\":\"user\",\"methods\":{\"__OvmSpokePool_init(uint32,address,address,address)\":{\"notice\":\"Construct the OVM SpokePool.\"},\"__SpokePool_init(uint32,address,address)\":{\"notice\":\"Construct the base SpokePool.\"},\"chainId()\":{\"notice\":\"Returns chain ID for this network.\"},\"deposit(address,address,uint256,uint256,int64,uint32,bytes,uint256)\":{\"notice\":\"Called by user to bridge funds from origin to destination chain. Depositor will effectively lock tokens in this contract and receive a destination token on the destination chain. The origin => destination token mapping is stored on the L1 HubPool.The caller must first approve this contract to spend amount of originToken.The originToken => destinationChainId must be enabled.This method is payable because the caller is able to deposit native token if the originToken is wrappedNativeToken and this function will handle wrapping the native token to wrappedNativeToken.\"},\"depositExclusive(address,address,address,address,uint256,uint256,uint256,address,uint32,uint32,uint32,bytes)\":{\"notice\":\"Submits deposit and sets exclusivityDeadline to current time plus some offset. This function is designed to be called by users who want to set an exclusive relayer for some amount of time after their deposit transaction is mined.If exclusivtyDeadlineOffset > 0, then exclusiveRelayer must be set to a valid address, which is a requirement imposed by depositV3().\"},\"depositFor(address,address,address,uint256,uint256,int64,uint32,bytes,uint256)\":{\"notice\":\"The only difference between depositFor and deposit is that the depositor address stored in the relay hash can be overridden by the caller. This means that the passed in depositor can speed up the deposit, which is useful if the deposit is taken from the end user to a middle layer contract, like an aggregator or the SpokePoolVerifier, before calling deposit on this contract.The caller must first approve this contract to spend amount of originToken.The originToken => destinationChainId must be enabled.This method is payable because the caller is able to deposit native token if the originToken is wrappedNativeToken and this function will handle wrapping the native token to wrappedNativeToken.\"},\"depositV3(address,address,address,address,uint256,uint256,uint256,address,uint32,uint32,uint32,bytes)\":{\"notice\":\"Request to bridge input token cross chain to a destination chain and receive a specified amount of output tokens. The fee paid to relayers and the system should be captured in the spread between output amount and input amount when adjusted to be denominated in the input token. A relayer on the destination chain will send outputAmount of outputTokens to the recipient and receive inputTokens on a repayment chain of their choice. Therefore, the fee should account for destination fee transaction costs, the relayer's opportunity cost of capital while they wait to be refunded following an optimistic challenge window in the HubPool, and the system fee that they'll be charged.\"},\"depositV3Now(address,address,address,address,uint256,uint256,uint256,address,uint32,uint32,bytes)\":{\"notice\":\"Submits deposit and sets quoteTimestamp to current Time. Sets fill and exclusivity deadlines as offsets added to the current time. This function is designed to be called by users such as Multisig contracts who do not have certainty when their transaction will mine.\"},\"emergencyDeleteRootBundle(uint256)\":{\"notice\":\"This method is intended to only be used in emergencies where a bad root bundle has reached the SpokePool.\"},\"executeRelayerRefundLeaf(uint32,(uint256,uint256,uint256[],uint32,address,address[]),bytes32[])\":{\"notice\":\"Executes a relayer refund leaf stored as part of a root bundle. Will send the relayer the amount they sent to the recipient plus a relayer fee.\"},\"executeV3SlowRelayLeaf(((address,address,address,address,address,uint256,uint256,uint256,uint32,uint32,uint32,bytes),uint256,uint256),uint32,bytes32[])\":{\"notice\":\"Executes a slow relay leaf stored as part of a root bundle relayed by the HubPool.\"},\"fillV3Relay((address,address,address,address,address,uint256,uint256,uint256,uint32,uint32,uint32,bytes),uint256)\":{\"notice\":\"Fulfill request to bridge cross chain by sending specified output tokens to the recipient.\"},\"fillV3RelayWithUpdatedDeposit((address,address,address,address,address,uint256,uint256,uint256,uint32,uint32,uint32,bytes),uint256,uint256,address,bytes,bytes)\":{\"notice\":\"Identical to fillV3Relay except that the relayer wants to use a depositor's updated output amount, recipient, and/or message. The relayer should only use this function if they can supply a message signed by the depositor that contains the fill's matching deposit ID along with updated relay parameters. If the signature can be verified, then this function will emit a FilledV3Event that will be used by the system for refund verification purposes. In otherwords, this function is an alternative way to fill a a deposit than fillV3Relay.\"},\"getCurrentTime()\":{\"notice\":\"Gets the current time.\"},\"initialize(uint32,address,address)\":{\"notice\":\"Construct the OVM Zora SpokePool.\"},\"pauseDeposits(bool)\":{\"notice\":\"Pauses deposit-related functions. This is intended to be used if this contract is deprecated or when something goes awry.\"},\"pauseFills(bool)\":{\"notice\":\"Pauses fill-related functions. This is intended to be used if this contract is deprecated or when something goes awry.\"},\"relayRootBundle(bytes32,bytes32)\":{\"notice\":\"This method stores a new root bundle in this contract that can be executed to refund relayers, fulfill slow relays, and send funds back to the HubPool on L1. This method can only be called by the admin and is designed to be called as part of a cross-chain message from the HubPool's executeRootBundle method.\"},\"requestV3SlowFill((address,address,address,address,address,uint256,uint256,uint256,uint32,uint32,uint32,bytes))\":{\"notice\":\"Request Across to send LP funds to this contract to fulfill a slow fill relay for a deposit in the next bundle.\"},\"setCrossDomainAdmin(address)\":{\"notice\":\"Change cross domain admin address. Callable by admin only.\"},\"setEnableRoute(address,uint256,bool)\":{\"notice\":\"Enable/Disable an origin token => destination chain ID route for deposits. Callable by admin only.\"},\"setHubPool(address)\":{\"notice\":\"Change L1 hub pool address. Callable by admin only.\"},\"setL1GasLimit(uint32)\":{\"notice\":\"Change L1 gas limit. Callable only by admin.\"},\"setTokenBridge(address,address)\":{\"notice\":\"Set bridge contract for L2 token used to withdraw back to L1.\"},\"speedUpV3Deposit(address,uint32,uint256,address,bytes,bytes)\":{\"notice\":\"Depositor can use this function to signal to relayer to use updated output amount, recipient, and/or message.\"}},\"notice\":\"Zora Spoke pool.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Zora_SpokePool.sol\":\"Zora_SpokePool\"},\"debug\":{\"revertStrings\":\"strip\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[],\"viaIR\":true},\"sources\":{\"@eth-optimism/contracts/libraries/constants/Lib_PredeployAddresses.sol\":{\"keccak256\":\"0x2bc28307af93e9716151a41a81694b56cbe513ef5eb335fb1d81f35e5db8edfa\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bbdde142b16f7e0301b7b6a331b35ce609eaf5c9127f14f60c0008abb36e100f\",\"dweb:/ipfs/QmdKUiY6U2vh5egW1bYtvrNhpEmo4Jo4DEwUUmBCfW4eLy\"]},\"@openzeppelin/contracts-upgradeable/crosschain/errorsUpgradeable.sol\":{\"keccak256\":\"0xa1e9b651a2427925598b49ef35da5930abc07859cfac5b9dfb1912f063a024b3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c514518c36a3fb1c5f1a99d88857e93160c72ea1fd728c443406ad1acb43ae9a\",\"dweb:/ipfs/Qmc3oXjBNhdeM5cfWpsvewXZAhH34Scgna2W3MvLaiiapQ\"]},\"@openzeppelin/contracts-upgradeable/crosschain/optimism/LibOptimismUpgradeable.sol\":{\"keccak256\":\"0x4e749e196701e221283db53ccaafd372434cdaed2a0b1f5a81b23e36b826b3e8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c12147f335d1f8cfee08c853de86d06f63534fe8395f4f0c3c202c045f2ef4d2\",\"dweb:/ipfs/QmNnJzZGLymFtaaKn9zQAtxeNAGmXCDPFyjxzthkUTrKre\"]},\"@openzeppelin/contracts-upgradeable/interfaces/IERC1967Upgradeable.sol\":{\"keccak256\":\"0x47d6e06872b12e72c79d1b5eb55842f860b5fb1207b2317c2358d2766b950a7b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ac55bf6f92fc7b90c6d79d346163a0a02bd5c648c7fede08b20e5da96d4ae2a0\",\"dweb:/ipfs/QmQoSrHhka35iKDK5iyNt8cuXXS5ANXVPjLhfsJjktB8V9\"]},\"@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol\":{\"keccak256\":\"0x77c89f893e403efc6929ba842b7ccf6534d4ffe03afe31670b4a528c0ad78c0f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://496bd9b3df2455d571018c09f0c6badd29713fdeb907c6aa09d8d28cb603f053\",\"dweb:/ipfs/QmXdJDyYs6WMwMh21dez2BYPxhSUaUYFMDtVNcn2cgFR79\"]},\"@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol\":{\"keccak256\":\"0x7795808e3899c805254e3ae58074b20f799b466e3f43e057e47bedee5fb771f8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://319853a2a682f3f72411507242669ef5e76e0ad3457be53102439709ee8948f0\",\"dweb:/ipfs/QmRtm4Ese9u4jfxXyuWPXLwzenwFotuQjAWV7rXtZTB1E9\"]},\"@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol\":{\"keccak256\":\"0x24b86ac8c005b8c654fbf6ac34a5a4f61580d7273541e83e013e89d66fbf0908\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://4dbfe1a3b3b3fb64294ce41fd2ad362e7b7012208117864f42c1a67620a6d5c1\",\"dweb:/ipfs/QmVMU5tWt7zBQMmf5cpMX8UMHV86T3kFeTxBTBjFqVWfoJ\"]},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f103ee2e4aecd37aac6ceefe670709cdd7613dee25fa2d4d9feaf7fc0aaa155e\",\"dweb:/ipfs/QmRiNZLoJk5k3HPMYGPGjZFd2ke1ZxjhJZkM45Ec9GH9hv\"]},\"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\":{\"keccak256\":\"0xefb41f5c1a00249b7a99f0782f8c557865605426a3fb6e5fe9ae334293ae4f33\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://90def55e5782595aabc13f57780c02d3613e5226f20ce6c1709503a63fdeb58f\",\"dweb:/ipfs/Qmb5vcymmNEZUJMaHmYxnhvGJDEsGMae4YjcHwkA74jy99\"]},\"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\":{\"keccak256\":\"0x2025ccf05f6f1f2fd4e078e552836f525a1864e3854ed555047cd732320ab29b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d27f4b23c2dee42394aebaf42bf238285230f472dfd3282a39c3f000ec28214f\",\"dweb:/ipfs/QmQa3DnvccwdWJeWrjgXPnFMTWbzWQWR39hVqC7eEwo2PC\"]},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c25f742ff154998d19a669e2508c3597b363e123ce9144cd0fcf6521229f401f\",\"dweb:/ipfs/QmQXRuFzStEWqeEPbhQU6cAg9PaSowxJVo4PDKyRod7dco\"]},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1fed09b97ccb0ff9ba9b6a94224f1d489026bf6b4b7279bfe64fb6e8749dee4d\",\"dweb:/ipfs/QmcRAzaSP1UnGr4vrGkfJmB2L9aiTYoXfV1Lg9gqrVRWn8\"]},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d03ebe5406134f0c4a017dee625ff615031194493bd1e88504e5c8fae55bc166\",\"dweb:/ipfs/QmUZV5bMbgk2PAkV3coouSeSainHN2jhqaQDJaA7hQRyu2\"]},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://310136ad60820af4177a11a61d77a3686faf5fca4942b600e08fc940db38396b\",\"dweb:/ipfs/QmbCzMNSTL7Zi7M4UCSqBrkHtp4jjxUnGbkneCZKdR1qeq\"]},\"@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol\":{\"keccak256\":\"0x07ac95acad040f1fb1f6120dd0aa5f702db69446e95f82613721879d30de0908\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a9df9de7b5da1d1bd3d4b6c073d0174bc4211db60e794a321c8cb5d4eae34685\",\"dweb:/ipfs/QmWe49zj65jayrCe9jZpoWhYUZ1RiwSxyU2s7SBZnMztVy\"]},\"@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol\":{\"keccak256\":\"0xb96dc79b65b7c37937919dcdb356a969ce0aa2e8338322bf4dc027a3c9c9a7eb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f8613145881436fc0480fff22da4868d611e2b0c0c3da083334eb4362ce1945a\",\"dweb:/ipfs/QmPqpP3YeRbBdTJRe6Gv2eGsUaANf4J6RwTNRW36iYahfV\"]},\"@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol\":{\"keccak256\":\"0xa014f65d84b02827055d99993ccdbfb4b56b2c9e91eb278d82a93330659d06e4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://50a7e716a74f3d48a7f549086faa94afcd58b9f18ac8e9f74af4571f3a1d8d5c\",\"dweb:/ipfs/QmTkDNWkq5o9Cv2jS7s6JvSmsPBkeunZhPe7Z2njGL31wo\"]},\"@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol\":{\"keccak256\":\"0x2bc0007987c229ae7624eb29be6a9b84f6a6a5872f76248b15208b131ea41c4e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2b2835c737d073ef8b82a4cc246495a9740f43e7ff2cf130906b2449ff9bfb91\",\"dweb:/ipfs/QmSCWfNoSvvTN57ic7o1RW6NqSxxGAqbBTnLKc7QHe27qB\"]},\"@openzeppelin/contracts-upgradeable/utils/math/SignedMathUpgradeable.sol\":{\"keccak256\":\"0x88f6b7bba3ee33eeb741f9a0f5bc98b6e6e352d0fe4905377bb328590f84095a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://88ace2d60f265752f18903d839910be4e4e104340b2957678585b812447825d4\",\"dweb:/ipfs/QmXFkNxMc3AAGzhs2wUEZyErWQjsvoTGyYjuU5oZkFki5Z\"]},\"@openzeppelin/contracts-upgradeable/vendor/optimism/ICrossDomainMessengerUpgradeable.sol\":{\"keccak256\":\"0xb531a6941d55a97d0db7af85c19b6aaf7fc634e550b513daa28e874b2c9b2dfa\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://23b0ce75313d9863512271a51940f6876051a5cb6dce60dd06bc03e565631b9d\",\"dweb:/ipfs/QmZobv3VixcvPxVF6hZgWxo8ELd9nXK935aiBpyHypYSoL\"]},\"@openzeppelin/contracts/interfaces/IERC1271.sol\":{\"keccak256\":\"0x0705a4b1b86d7b0bd8432118f226ba139c44b9dcaba0a6eafba2dd7d0639c544\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c45b821ef9e882e57c256697a152e108f0f2ad6997609af8904cae99c9bd422e\",\"dweb:/ipfs/QmRKCJW6jjzR5UYZcLpGnhEJ75UVbH6EHkEa49sWx2SKng\"]},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bd39944e8fc06be6dbe2dd1d8449b5336e23c6a7ba3e8e9ae5ae0f37f35283f5\",\"dweb:/ipfs/QmPV3FGYjVwvKSgAXKUN3r9T9GwniZz83CxBpM7vyj2G53\"]},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"keccak256\":\"0xb264c03a3442eb37a68ad620cefd1182766b58bee6cec40343480392d6b14d69\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://28879d01fd22c07b44f006612775f8577defbe459cb01685c5e25cd518c91a71\",\"dweb:/ipfs/QmVgfkwv2Fxw6hhTcDUZhE7NkoSKjab3ipM7UaRbt6uXb5\"]},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9d213d3befca47da33f6db0310826bcdb148299805c10d77175ecfe1d06a9a68\",\"dweb:/ipfs/QmRgCn6SP1hbBkExUADFuDo8xkT4UU47yjNF5FhCeRbQmS\"]},\"@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2455248c8ddd9cc6a7af76a13973cddf222072427e7b0e2a7d1aff345145e931\",\"dweb:/ipfs/QmfYjnjRbWqYpuxurqveE6HtzsY1Xx323J428AKQgtBJZm\"]},\"@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b81d9ff6559ea5c47fc573e17ece6d9ba5d6839e213e6ebc3b4c5c8fe4199d7f\",\"dweb:/ipfs/QmPCW1bFisUzJkyjroY3yipwfism9RRCigCcK1hbXtVM8n\"]},\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"keccak256\":\"0x809bc3edb4bcbef8263fa616c1b60ee0004b50a8a1bfa164d8f57fd31f520c58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8b93a1e39a4a19eba1600b92c96f435442db88cac91e315c8291547a2a7bcfe2\",\"dweb:/ipfs/QmTm34KVe6uZBZwq8dZDNWwPcm24qBJdxqL3rPxBJ4LrMv\"]},\"@openzeppelin/contracts/utils/cryptography/MerkleProof.sol\":{\"keccak256\":\"0xcf688741f79f4838d5301dcf72d0af9eff11bbab6ab0bb112ad144c7fb672dac\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://85d9c87a481fe99fd28a146c205da0867ef7e1b7edbe0036abc86d2e64eb1f04\",\"dweb:/ipfs/QmR7m1zWQNfZHUKTtqnjoCjCBbNFcjCxV27rxf6iMfhVtG\"]},\"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\":{\"keccak256\":\"0x3af3ca86df39aac39a0514c84459d691434a108d2151c8ce9d69f32e315cab80\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://77d1f1cf302cd5e1dfbbb4ce3b281b28e8c52942d4319fce43df2e1b6f02a52d\",\"dweb:/ipfs/QmT6ZXStmK3Knhh9BokeVHQ9HXTBZNgL3Eb1ar1cYg1hWy\"]},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://cc8841b3cd48ad125e2f46323c8bad3aa0e88e399ec62acb9e57efa7e7c8058c\",\"dweb:/ipfs/QmSqE4mXHA2BXW58deDbXE8MTcsL5JSKNDbm23sVQxRLPS\"]},\"@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c50fcc459e49a9858b6d8ad5f911295cb7c9ab57567845a250bf0153f84a95c7\",\"dweb:/ipfs/QmcEW85JRzvDkQggxiBBLVAasXWdkhEysqypj9EaB6H2g6\"]},\"contracts/MerkleLib.sol\":{\"keccak256\":\"0xdaf19fdc82593b79a608af8f691aec89a3c0e47b210770deabbe66ece7c35bb1\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://03c37f78657beed37257187e237d74492de0199734aa03272a419f66161c0dca\",\"dweb:/ipfs/QmdcXMAoRLZejhh2xcVMWR3WfUvXcArKrCFEE82JDYiJbh\"]},\"contracts/Ovm_SpokePool.sol\":{\"keccak256\":\"0xafda58b392d0fa19f8fd8692d7718c4ea08645f6f4d63509f69e88efe6d18611\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://036bce2642bc769b7f6656d9d867c2aef69205610555d991e2f65607e7b30d4a\",\"dweb:/ipfs/QmVMcWcEFjMbrrboLK3pnnegamcPiowz8hC2UUULxj6TVN\"]},\"contracts/SpokePool.sol\":{\"keccak256\":\"0x83ed55d42cb076159f2871e4365f89950d03f6d55cec01badf23f34b07a3c0b5\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://3722416534f49998f19deb1b694126aea67908dd97f975d10ef261c789b2b2de\",\"dweb:/ipfs/QmXCJuhfiovJyxKWHXDZwFnoXDESyQyHWXJEpXsb5JQo2Z\"]},\"contracts/Zora_SpokePool.sol\":{\"keccak256\":\"0xb0cc3a9d60b1a35d6bbe478daeed564e3d49137ecb575db876fd2dd5f660e3da\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://acf9558167596f63933ccdad0781685f82cad6f8900a021748d5c709c93549f3\",\"dweb:/ipfs/QmRb6HJVSDX5hip3RskUVFQqb3Y6ddwrpK8ZFx1GeKNsot\"]},\"contracts/external/interfaces/CCTPInterfaces.sol\":{\"keccak256\":\"0x9d6606bb3b0c52bcdbe834d4bc2cb97db6bfd2a906178598f5891d662d0450bd\",\"license\":\"GPL-3.0-or-later\",\"urls\":[\"bzz-raw://ea9e6c3116639844d38dc654a7736fed3d6c3649f26c182f2aa4a2836546a3e0\",\"dweb:/ipfs/QmeBjv9R4RkJc3BxmijBosbWZLNh3cbkcoZvznLh7rXHqr\"]},\"contracts/external/interfaces/WETH9Interface.sol\":{\"keccak256\":\"0x3f7892554ec7f54681fdd3cc18a41346c246c9c1afba016c52990ef77741f718\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://76e901f8da798eb2fdef8fd0083a51088103269f08ee751598c5a6eba407785f\",\"dweb:/ipfs/QmcAHbwbwCZd78teaK4cHuAvXq71aWX1r9vTGkSRRBDJV1\"]},\"contracts/interfaces/HubPoolInterface.sol\":{\"keccak256\":\"0xefd509ab379b94004b5767d67971e5c0bda4ca1e9f376b5aea75a0297b5d7bd6\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://0b7e509e90bcca9b96bf55e92498b17bbb548359c470b17285740080a6c0d9de\",\"dweb:/ipfs/QmdviQBbB58H9HR3tKQepEuYcMKXZthyTThGXUgQDAC828\"]},\"contracts/interfaces/SpokePoolInterface.sol\":{\"keccak256\":\"0xc90fbd7e66e2e87e9aacbe93c20cc020cd1fc582c4fd4879807e7dc026943ea0\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://d28aa2c818e1f172468872f0a36ea22f2df4c00f733cf9f6ee97f4e3fbb3b376\",\"dweb:/ipfs/QmQvPWH9HTikNdRsaBgQ2Z1JrHB3gJ2iR9bzEiXhA5TWCE\"]},\"contracts/interfaces/SpokePoolMessageHandler.sol\":{\"keccak256\":\"0xef7377f05d40e665eb346fb1647e1341558ce5fd1e03768d81a41a579365ff47\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://6689551ad226c66bbab84387f193445ab209bf795f17ce4cf1be9ab5c1984e5d\",\"dweb:/ipfs/Qme3XnW4RZJruCDJTV8MNQsjJj14qPWZHLQZJhY4rh1iV6\"]},\"contracts/interfaces/V3SpokePoolInterface.sol\":{\"keccak256\":\"0x374b7e9cb8afbcaec69cdbcde480676b5d927db84c7f38221331d1226af68d9d\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://bb2b4edc4ad2999fdb785b74b7e70fbe2f05a0e87f8133adcd932cc8c58be461\",\"dweb:/ipfs/QmeNjPQQhBTPvkWPXd8mdApbqPu8iXRr1MkyRDJtAQFAQX\"]},\"contracts/libraries/CircleCCTPAdapter.sol\":{\"keccak256\":\"0x04481a0fe0c4a39c047d485a1f7563b737417fadb6cb42ceb4d0b286493d8124\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://f0c6e5ac8438c7f4a216e990d497f68fffe905abc18ac043c2ada56d463657a4\",\"dweb:/ipfs/QmYr9j9FMJjJdRiUCADjF6zcp49p8dbL2VAcsuPz7uxJKD\"]},\"contracts/upgradeable/AddressLibUpgradeable.sol\":{\"keccak256\":\"0x655040da45a857cf609d7176c7b0647bf76d36e73e856af79d511014c7e8ef81\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5c17767f34d57380767b49f8584d62598964fc813e6f3587d76b51ec2357bb4e\",\"dweb:/ipfs/QmSyoTa1Snn3KiJD7KjCwsPmNqpJzusXterbEXxbYCZoJK\"]},\"contracts/upgradeable/EIP712CrossChainUpgradeable.sol\":{\"keccak256\":\"0xff617722706d1c0a6d346e56e4598cc5f60adea99b4ac1d2347dcd69270a14f6\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://e2d04649c09bad766c5632da2e3a4f1deed1e013e8b713fad1f101e06f4b56a3\",\"dweb:/ipfs/QmfCewdTDr2krzvNY5rH5BprngEtBmxPXCZf6JKavxw2Sb\"]},\"contracts/upgradeable/MultiCallerUpgradeable.sol\":{\"keccak256\":\"0xc1378a7d63785d9381b8fb6e42962499ab26a243292e20981c2792511a4697f3\",\"license\":\"BUSL-1.1\",\"urls\":[\"bzz-raw://2ec8d733e528d6e79732409eb04aa5f8a8bcdf5888e677919a07d8b84afb1598\",\"dweb:/ipfs/QmQF23Gf9vHb6Ne6kaEZmQTjobWzasEWWr5YaBFkuEypz4\"]}},\"version\":1}", "bytecode": "0x61016034620001e957601f6200517d38819003918201601f19168301916001600160401b03831184841017620001ed5780849260a094604052833981010312620001e95780516001600160a01b03919082811690819003620001e957620000696020830162000201565b620000776040840162000201565b916060840151938585168503620001e957608001519485168503620001e9573060805260a05260c05260e0525f5460ff8160081c16620001e95760ff80821603620001ae575b50610120908152610140918252610100915f835260405191614f699384620002148539608051848181610c9f015281816113180152611492015260a05184818161079c01528181611a1c01528181612d08015281816133ac0152818161351001528181613c6501528181613f35015281816143db0152818161478901526147b0015260c051848181611593015281816119c301528181612caf015261333e015260e0518481816103b301528181611c030152612e3c0152518381816117020152614d2801525182818161073f015281816147470152614c22015251818181611d4a015281816145000152614c4e0152f35b60ff90811916175f557f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498602060405160ff8152a15f620000bd565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b519063ffffffff82168203620001e95756fe6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c8063079bd2c7146103845780630c5d5f731461037f5780630eaac9f01461037a5780631186ec331461037557806311eac8551461037057806315348e441461030757806317fcb39b1461036b5780631b3d5559146103665780631dfb2d0214610361578063272751c71461035c57806329cb924d146103575780632cfc26c5146103525780632e3781151461034d5780633659cfe614610348578063431023b814610343578063437b91161461033e578063493a4f84146103395780634e0fb8f5146103345780634f1ef2861461032f5780635249fef11461032a5780635285e0581461032557806352d1902d14610320578063541f4f141461031b57806357f6dcb8146103165780636068d6cb14610311578063647c576c1461030c5780636bbbcd2e146103075780636e40098314610302578063738b62e5146102fd578063766e0703146102f85780637aef642c146102f35780637b939232146102ee5780638a7860ce146102e9578063927ede2d146102e45780639748cf7c146102df578063979f2bc2146102da5780639963e5a8146102d557806399cc2968146102d05780639a8a0592146102cb578063a1244c67146102c6578063ac9650d8146102c1578063add051a3146102bc578063b27a4300146102b7578063bbca7db0146102b2578063bf10268d146102ad578063c35c83fc146102a8578063ccfa5971146102a3578063ceb4c9871461029e578063dda5211314610299578063ddd224f114610294578063de7eba781461028f578063e19044021461028a578063e322921114610285578063ee2a53f8146102805763fbbba9ac0361000e576126cd565b61268f565b612613565b6125ec565b6125bc565b612593565b61256d565b61254f565b6124cc565b6124a1565b61241d565b6122dc565b61229d565b612227565b612187565b6120fd565b6120e3565b612035565b611e3c565b611d6e565b611d2b565b611cfd565b611c85565b61193e565b6117f9565b6117d5565b611726565b6116e6565b610763565b61160f565b6115b7565b611577565b6114e2565b611478565b611451565b611403565b6112d5565b6111bb565b611106565b611039565b610da9565b610c77565b610b24565b610adb565b610ac1565b610a22565b6109e3565b61090b565b61077d565b610720565b610667565b61044d565b6103f5565b610397565b5f91031261039357565b5f80fd5b34610393575f36600319011261039357602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6001600160a01b0381160361039357565b35906103f3826103d7565b565b34610393576020366003190112610393576020600435610414816103d7565b6001600160a01b038091165f52610c5d825260405f205416604051908152f35b63ffffffff81160361039357565b35906103f382610434565b346103935760203660031901126103935763ffffffff60043561046f81610434565b610477613144565b61047f613256565b16610c5a8163ffffffff198254161790557fe486a5c4bd7b36eabbfe274c99b39130277417be8d2209b4dae04c4fba64ee3a5f80a26001606555005b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff8211176104eb57604052565b6104bb565b67ffffffffffffffff81116104eb57604052565b6060810190811067ffffffffffffffff8211176104eb57604052565b6020810190811067ffffffffffffffff8211176104eb57604052565b60e0810190811067ffffffffffffffff8211176104eb57604052565b60a0810190811067ffffffffffffffff8211176104eb57604052565b90601f8019910116810190811067ffffffffffffffff8211176104eb57604052565b6040519060c0820182811067ffffffffffffffff8211176104eb57604052565b60405190610180820182811067ffffffffffffffff8211176104eb57604052565b604051906080820182811067ffffffffffffffff8211176104eb57604052565b67ffffffffffffffff81116104eb57601f01601f191660200190565b92919261061f826105f7565b9161062d6040519384610574565b829481845281830111610393578281602093845f960137010152565b9080601f830112156103935781602061066493359101610613565b90565b61010036600319011261039357600435610680816103d7565b60243561068c816103d7565b6084358060070b81036103935760a435906106a682610434565b60c43567ffffffffffffffff8111610393576106c6903690600401610649565b926106cf613256565b60ff61086b5460e81c166106f6576106ef946064359160443591336132c5565b6001606555005b60046040517f5a65d188000000000000000000000000000000000000000000000000000000008152fd5b34610393575f3660031901126103935760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610393575f3660031901126103935760206040515f8152f35b34610393575f3660031901126103935760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b67ffffffffffffffff81116104eb5760051b60200190565b9080601f830112156103935760209082356107f2816107c0565b936108006040519586610574565b81855260208086019260051b82010192831161039357602001905b828210610829575050505090565b8135815290830190830161081b565b9080601f83011215610393576020908235610852816107c0565b936108606040519586610574565b81855260208086019260051b82010192831161039357602001905b828210610889575050505090565b8380918335610897816103d7565b81520191019061087b565b92916108ad826107c0565b916108bb6040519384610574565b829481845260208094019160051b810192831161039357905b8282106108e15750505050565b813581529083019083016108d4565b9080601f8301121561039357816020610664933591016108a2565b6003196060368201126103935760043561092481610434565b60243567ffffffffffffffff928382116103935760c09082360301126103935761094c610596565b90806004013582526024810135602083015260448101358481116103935761097a90600436918401016107d8565b604083015261098b60648201610442565b606083015261099c608482016103e8565b608083015260a4810135908482116103935760046109bd9236920101610838565b60a0820152604435928311610393576109dd6100189336906004016108f0565b91612751565b34610393576020366003190112610393576106ef600435610a03816103d7565b610a0b613144565b610a13613256565b6137da565b8015150361039357565b3461039357606036600319011261039357600435610a3f816103d7565b602435907f0a21fdd43d0ad0c62689ee7230a47309a050755bcc52eba00310add65297692a60206001600160a01b0360443593610a7b85610a18565b610a83613144565b610a8b613256565b1692835f5261086d825260405f20855f52825260405f209015159060ff1981541660ff8316179055604051908152a36001606555005b34610393575f366003190112610393576020604051428152f35b34610393575f3660031901126103935760206040517f152eb71524aef34d838ab76573c14b1ebfa5e385d9ab29d7cf5398daa2438bd98152f35b90816101809103126103935790565b346103935760403660031901126103935760043567ffffffffffffffff811161039357610b55903690600401610b15565b610b5d613256565b60ff61086b5460e01c16610c6657610b786101408201612944565b63ffffffff429116101580610c48575b610c1e57610c1490610c00610ba5610ba03684612958565b613918565b9160c0610bf9610bb76020840161294e565b610bc5610160850185612a38565b939094610bd0610596565b97610bdb3683612958565b89526020890152013560408701526001600160a01b03166060860152565b3691610613565b608082015260243560a08201523390613a6b565b6100186001606555565b60046040517fc3a9b9d0000000000000000000000000000000000000000000000000000000008152fd5b50610c556040820161294e565b6001600160a01b0316331415610b88565b6004604051633d90fc5560e11b8152fd5b3461039357602036600319011261039357600435610c94816103d7565b6001600160a01b03807f000000000000000000000000000000000000000000000000000000000000000016803014610393577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90828254160361039357610cf9613144565b60405191610d0683610520565b5f83527f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615610d3f5750505061001890614948565b6020600491604051928380926352d1902d60e01b825288165afa5f9181610d78575b50610d6a575f80fd5b03610393576100189161482f565b610d9b91925060203d602011610da2575b610d938183610574565b81019061402d565b905f610d61565b503d610d89565b3461039357608036600319011261039357600435610dc681610434565b60243590610dd3826103d7565b604435610ddf816103d7565b60643591610dec836103d7565b60ff5f5460081c161561039357610e3390610c5a624c4b4063ffffffff1982541617905561086b9063ffffffff60c01b1963ffffffff60c01b83549260c01b169116179055565b60405190610e40826104cf565b6009825260208201916820a1a927a9a996ab1960b91b8352640312e302e360dc1b6020604051610e6f816104cf565b60058152015260ff5f5460081c16156103935761001894610ecf93610a139251902061047f557f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c61048055610ec261419f565b610eca6141ae565b6141c2565b610c5a907fffffffffffffffff0000000000000000000000000000000000000000ffffffff77ffffffffffffffffffffffffffffffffffffffff0000000083549260201b169116179055565b9181601f840112156103935782359167ffffffffffffffff8311610393576020808501948460051b01011161039357565b6020600319820112610393576004359067ffffffffffffffff821161039357610f7791600401610f1b565b9091565b5f5b838110610f8c5750505f910152565b8181015183820152602001610f7d565b90602091610fb581518092818552858086019101610f7b565b601f01601f1916010190565b6020808201908083528351809252604092604081018260408560051b8401019601945f925b858410610ff7575050505050505090565b909192939495968580611028600193603f1986820301885286838d5180511515845201519181858201520190610f9c565b990194019401929594939190610fe6565b346103935761104736610f4c565b611050816107c0565b9160406110606040519485610574565b828452601f1961106f846107c0565b015f5b8181106110e35750505f5b83811061109657604051806110928782610fc1565b0390f35b806110dd6110a660019388612a6b565b515f806110b4858a8a612a7f565b906110c3895180938193612a96565b0390305af4906110d1612aa3565b60208201529015159052565b0161107d565b60209083516110f1816104cf565b5f815282606081830152828901015201611072565b3461039357604036600319011261039357602435600435611125613144565b61112d613256565b61086c8054680100000000000000008110156104eb5763ffffffff916001820190558361115982612650565b5084600182015555167fc86ba04c55bc5eb2f2876b91c438849a296dbec7b08751c3074d92e04f0a77af5f80a46001606555005b9181601f840112156103935782359167ffffffffffffffff8311610393576020838186019501011161039357565b346103935760c0366003190112610393576004356111d8816103d7565b602435906111e582610434565b6044356064356111f4816103d7565b67ffffffffffffffff916084358381116103935761121690369060040161118d565b93909460a435918211610393576112b963ffffffff7fb0a29aed3d389a1041194255878b423f7780be3ed2324d4693508c6ff189845e9661125e6112cb95369060040161118d565b939099611269613256565b6112908c8c8b8b61128761127e368a89610613565b938b3691610613565b9346908c61403c565b6001600160a01b0392836040519a8b9a8b521660208a0152608060408a01526080890191612ad2565b93868503606088015216981696612ad2565b0390a36001606555005b6040366003190112610393576004356112ed816103d7565b60243567ffffffffffffffff81116103935761130d903690600401610649565b6001600160a01b03807f00000000000000000000000000000000000000000000000000000000000000001690813014610393577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc91818354160361039357611373613144565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff16156113a95750505061001890614948565b6020600491604051928380926352d1902d60e01b825288165afa5f91816113e2575b506113d4575f80fd5b0361039357610018916148f7565b6113fc91925060203d602011610da257610d938183610574565b905f6113cb565b34610393576040366003190112610393576001600160a01b03600435611428816103d7565b165f5261086d60205260405f206024355f52602052602060ff60405f2054166040519015158152f35b34610393575f3660031901126103935760206001600160a01b036108695416604051908152f35b34610393575f366003190112610393576001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036103935760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b610120366003190112610393576004356114fb816103d7565b60243590611508826103d7565b60443591611515836103d7565b60a4358060070b81036103935760c4359161152f83610434565b60e43567ffffffffffffffff81116103935761154f903690600401610649565b93611558613256565b60ff61086b5460e81c166106f6576106ef9560843592606435926132c5565b34610393575f36600319011261039357602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610393575f36600319011261039357602060ff61086b5460e81c166040519015158152f35b6060906003190112610393576004356115f581610434565b90602435611602816103d7565b90604435610664816103d7565b346103935761161d366115dd565b5f54600881901c60ff16159392908490816116d8575b81156116b8575b50156103935761165e9284611655600160ff195f5416175f55565b6116a157612af2565b61166457005b61167261ff00195f54165f55565b604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb384740249890602090a1005b6116b361010061ff00195f5416175f55565b612af2565b303b159150816116ca575b505f61163a565b6001915060ff16145f6116c3565b600160ff8216109150611633565b34610393575f36600319011261039357602060405163ffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610393576020366003190112610393577fe88463c2f254e2b070013a2dc7ee1e099f9bc00534cbdf03af551dc26ae49219602060043561176681610a18565b61176e613144565b611776613256565b151561086b80547fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7dff00000000000000000000000000000000000000000000000000000000008460e81b169116179055604051908152a16001606555005b34610393575f36600319011261039357602063ffffffff610c5a5416604051908152f35b61016036600319011261039357600435611812816103d7565b6024359061181f826103d7565b60443561182b816103d7565b60643590611838826103d7565b60e435611844816103d7565b610104359061185282610434565b610124359261186084610434565b610144359667ffffffffffffffff88116103935761188561001898369060040161118d565b97909660c4359360a4359360843593612c3f565b90610180600319830112610393576004356118b3816103d7565b916024356118c0816103d7565b916044356118cd816103d7565b916064356118da816103d7565b916084359160a4359160c4359160e4356118f3816103d7565b916101043561190181610434565b916101243561190f81610434565b916101443561191d81610434565b91610164359067ffffffffffffffff821161039357610f779160040161118d565b61194736611899565b959996989a9290949361195b9c989c613256565b61086b9960ff8b5460e81c166106f6576119a96119a561199e8e6119918d6001600160a01b03165f5261086d60205260405f2090565b905f5260205260405f2090565b5460ff1690565b1590565b611c5b5763ffffffff9d8e6119c081851642612e6a565b907f00000000000000000000000000000000000000000000000000000000000000001610611c31578e808516428110918215611bfb575b5050611bd1578e9b6001600160a01b039c8d891690871690818117611b6b575b50508c7f0000000000000000000000000000000000000000000000000000000000000000168d8c1681811480611b62575b15611b485750823403611b1e57803b15610393575f60049160405192838092630d0e30db60e41b825234905af18015611b1957611b00575b505b5460c01c63ffffffff169e8f611a9790612e8f565b611abe9061086b9063ffffffff60c01b1963ffffffff60c01b83549260c01b169116179055565b6040519c8d9c169f169d611ad29a8c612ea4565b037fa123dc29aebf7d0c3322c8eeb5b999e859f39937950ed31056532713d0de396f91a46100186001606555565b80611b0d611b13926104f0565b80610389565b5f611a80565b612e84565b60046040517f6452a35d000000000000000000000000000000000000000000000000000000008152fd5b905034611b1e5782611b5d9130903390614142565b611a82565b50341515611a48565b15611ba7574211611b7d575f80611a17565b60046040517f25a63a5b000000000000000000000000000000000000000000000000000000008152fd5b60046040517f495d907f000000000000000000000000000000000000000000000000000000008152fd5b60046040517f582e3889000000000000000000000000000000000000000000000000000000008152fd5b611c299192507f00000000000000000000000000000000000000000000000000000000000000001642612e77565b108f806119f7565b60046040517ff722177f000000000000000000000000000000000000000000000000000000008152fd5b60046040517f2a58c4f3000000000000000000000000000000000000000000000000000000008152fd5b3461039357602036600319011261039357600435611ca1613144565b611ca9613256565b611cb281612650565b611cea576001815f80935501557f3569b846531b754c99cb80df3f49cd72fa6fe106aaee5ab8e0caf35a9d7ce88d5f80a26001606555005b634e487b7160e01b5f525f60045260245ffd5b34610393575f3660031901126103935760206040517342000000000000000000000000000000000000078152f35b34610393575f3660031901126103935760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461039357611d7c366115dd565b909160ff5f5460081c161561039357611db29061086b9063ffffffff60c01b1963ffffffff60c01b83549260c01b169116179055565b604051611dbe816104cf565b6009815260208101926820a1a927a9a996ab1960b91b8452640312e302e360dc1b6020604051611ded816104cf565b60058152015260ff5f5460081c16156103935761001893610a139251902061047f557f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c61048055610ec261419f565b34610393576020366003190112610393576004803567ffffffffffffffff811161039357611e6d9036908301610b15565b611e75613256565b60ff61086b5460e01c1661202557610140810191611e9283612944565b9063ffffffff91824291161015611ffd5761012083019042611ebf611eb684612944565b63ffffffff1690565b10611fee57611ed1610ba03686612958565b90611ee5825f5261087260205260405f2090565b54611fc6575090611f2a611f247f923794976d026d6b119735adc163cb71decfc903e17c3dc226c00789593c04e194935f5261087260205260405f2090565b60019055565b611fb9611f396060860161294e565b95611f466080870161294e565b95611f66611f60611f5a6101008401612944565b95612944565b92612944565b611f726040830161294e565b611f7b8361294e565b90611f886020850161294e565b92611f97610160860186612a38565b9690956040519a8b9a169d60e08201359d60a060c0840135930135918c612f2f565b0390a36100186001606555565b6040517f012f9e44000000000000000000000000000000000000000000000000000000008152fd5b60405163d642b7d960e01b8152fd5b6040517f09deb9ec000000000000000000000000000000000000000000000000000000008152fd5b50604051633d90fc5560e11b8152fd5b34610393576020366003190112610393577f2d5b62420992e5a4afce0e77742636ca2608ef58289fd2e1baa5161ef6e7e41e602060043561207581610a18565b61207d613144565b612085613256565b151561086b80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff7cff000000000000000000000000000000000000000000000000000000008460e01b169116179055604051908152a16001606555005b34610393575f366003190112610393576020604051468152f35b34610393575f36600319011261039357602063ffffffff61086b5460c01c16604051908152f35b6020808201906020835283518092526040830192602060408460051b8301019501935f915b8483106121595750505050505090565b9091929394958480612177600193603f198682030187528a51610f9c565b9801930193019194939290612149565b346103935761219536610f4c565b9061219f82612f97565b915f5b8181106121b757604051806110928682612124565b5f806121c4838587612a7f565b906121d460405180938193612a96565b0390305af46121e1612aa3565b901561220757906001916121f58287612a6b565b526122008186612a6b565b50016121a2565b604481511061039357806004610393920151602480918301019101612fe0565b61223036611899565b959996919b97989a9290949361224d63ffffffff9d8e4216612c22565b92612256613256565b61086b9a60ff8c5460e81c166106f65761228c6119a561199e8f6119918e6001600160a01b03165f5261086d60205260405f2090565b611c5b578e6119c081851642612e6a565b346103935760203660031901126103935760206004356122bc816103d7565b6001600160a01b038091165f52610c5c825260405f205416604051908152f35b34610393576003196060368201126103935760043567ffffffffffffffff80821161039357606082360393840112610393576024359061231b82610434565b60443590811161039357612333903690600401610f1b565b91909361233e613256565b600484013590610182190181121561039357610c14946123f39361236b6123ec9360043691890101612958565b9561238861238360808901516001600160a01b031690565b613506565b6123da61239488613918565b9160446123ab60208b01516001600160a01b031690565b916101608b0151946123bb610596565b9b8c5260208c0152013560408a01526001600160a01b03166060890152565b60808701525f60a087015236916108a2565b9083614234565b613d76565b604090600319011261039357600435612410816103d7565b90602435610664816103d7565b346103935761242b366123f8565b90612434613144565b61243c613256565b6001600160a01b0380911691825f52610c5d6020526124748160405f20906001600160a01b03166001600160a01b0319825416179055565b16907fcb84c2022106a6f2b6f805d446f32fbfd2a528474364fa755f37dac1c0c1b6c85f80a36001606555005b34610393576020366003190112610393576004355f52610872602052602060405f2054604051908152f35b346103935760c03660031901126103935767ffffffffffffffff600435818111610393576124fe903690600401610b15565b6064359061250b826103d7565b6084358381116103935761252390369060040161118d565b9060a4359485116103935761253f61001895369060040161118d565b949093604435906024359061303f565b34610393575f36600319011261039357602060405163ffffffff8152f35b34610393575f36600319011261039357602060ff61086b5460e01c166040519015158152f35b34610393575f3660031901126103935760206040516ec097ce7bc90715b34b9f10000000008152f35b34610393576020366003190112610393576106ef6004356125dc816103d7565b6125e4613144565b610eca613256565b34610393575f3660031901126103935760206001600160a01b0361086a5416604051908152f35b34610393575f366003190112610393576020610c5a546001600160a01b0360405191831c168152f35b634e487b7160e01b5f52603260045260245ffd5b61086c90815481101561268a576003915f52027f71cd7344f4eb2efc8e30291f6dbdb44d618ca368ea5425d217c1d604bf26b84d01905f90565b61263c565b346103935760203660031901126103935760043561086c54811015610393576126b9604091612650565b506001815491015482519182526020820152f35b34610393576126db366123f8565b906126e4613144565b6126ec613256565b6001600160a01b0380911691825f52610c5c6020526127248160405f20906001600160a01b03166001600160a01b0319825416179055565b16907ff3dc137d2246f9b8abd0bb821e185ba01122c9b3ea3745ffca6208037674d6705f80a36001606555005b9161275a613256565b608082019161277361238384516001600160a01b031690565b602081019182514603612874576119a561279b9183600161279389612650565b5001546135b5565b612863578060607ff8bd640004bcec1b89657020f561d0b070cbdf662d0b158db9dccb0a8301bfab9201936127dd6127d7865163ffffffff1690565b87613675565b61285684519461283b61282d85519561281d60408201998a516128048d5163ffffffff1690565b89516001600160a01b03169160a086019b8c51946136e2565b5192519751985163ffffffff1690565b93516001600160a01b031690565b935163ffffffff9485604051968796169a169833938661289e565b0390a46103f36001606555565b600460405163582f497d60e11b8152fd5b60046040517f7a47c9a2000000000000000000000000000000000000000000000000000000008152fd5b95949392919060a0870190875260209060a08289015282518091528160c089019301905f5b818110612930575050506001600160a01b03809316604088015286820360608801528080855193848152019401925f905b8382106129175750505050509060806103f3929401906001600160a01b03169052565b84518116865294820194938201936001909101906128f4565b8251855293830193918301916001016128c3565b3561066481610434565b35610664816103d7565b9190610180838203126103935761296d6105b6565b92612977816103e8565b8452612985602082016103e8565b6020850152612996604082016103e8565b60408501526129a7606082016103e8565b60608501526129b8608082016103e8565b608085015260a081013560a085015260c081013560c085015260e081013560e08501526101006129e9818301610442565b908501526101206129fb818301610442565b90850152610140612a0d818301610442565b90850152610160918282013567ffffffffffffffff811161039357612a329201610649565b90830152565b903590601e1981360301821215610393570180359067ffffffffffffffff82116103935760200191813603831361039357565b805182101561268a5760209160051b010190565b9082101561268a57610f779160051b810190612a38565b908092918237015f815290565b3d15612acd573d90612ab4826105f7565b91612ac26040519384610574565b82523d5f602084013e565b606090565b908060209392818452848401375f828201840152601f01601f1916010190565b91909160ff5f5460081c161561039357612b3c90610c5a624c4b4063ffffffff1982541617905561086b9063ffffffff60c01b1963ffffffff60c01b83549260c01b169116179055565b604051612b48816104cf565b6009815260208101926820a1a927a9a996ab1960b91b8452640312e302e360dc1b6020604051612b77816104cf565b60058152015260ff5f5460081c161561039357612bc693610a139251902061047f557f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c61048055610ec261419f565b6103f3610c5a77deaddeaddeaddeaddeaddeaddeaddeaddead0000000000007fffffffffffffffff0000000000000000000000000000000000000000ffffffff825416179055565b634e487b7160e01b5f52601160045260245ffd5b91909163ffffffff80809416911601918211612c3a57565b612c0e565b96929993979a94989091959863ffffffff9b612c5e8d42169182612c22565b91612c67613256565b61086b9a60ff8c5460e81c166106f657612c9d6119a561199e8f6119918e6001600160a01b03165f5261086d60205260405f2090565b611c5b578e612cac8442612e6a565b907f00000000000000000000000000000000000000000000000000000000000000001610611c31578e808516428110918215612e34575b5050611bd1578e9b6001600160a01b039c8d891690871690818117612e22575b50508c7f0000000000000000000000000000000000000000000000000000000000000000168d8c1681811480612e19575b15612dff5750823403611b1e57803b15610393575f60049160405192838092630d0e30db60e41b825234905af18015611b1957612dec575b505b5460c01c63ffffffff169e8f612d8390612e8f565b612daa9061086b9063ffffffff60c01b1963ffffffff60c01b83549260c01b169116179055565b6040519c8d9c169f169d612dbe9a8c612ea4565b037fa123dc29aebf7d0c3322c8eeb5b999e859f39937950ed31056532713d0de396f91a46103f36001606555565b80611b0d612df9926104f0565b5f612d6c565b905034611b1e5782612e149130903390614142565b612d6e565b50341515612d34565b15611ba7574211611b7d575f80612d03565b612e629192507f00000000000000000000000000000000000000000000000000000000000000001642612e77565b108f80612ce3565b91908203918211612c3a57565b91908201809211612c3a57565b6040513d5f823e3d90fd5b63ffffffff809116908114612c3a5760010190565b6001600160a01b03918216815291811660208301526040820192909252606081019290925263ffffffff928316608083015292821660a0820152921660c083015291821660e08201529116610100820152610140610120820181905261066493910191612ad2565b634e487b7160e01b5f52602160045260245ffd5b60031115612f2a57565b612f0c565b96909193979295946106649b9995610140996001600160a01b0398898098818098168d521660208c015260408b015260608a015263ffffffff80921660808a01521660a08801521660c08601521660e084015216610100820152816101208201520191612ad2565b90612fa1826107c0565b612fae6040519182610574565b8281528092612fbf601f19916107c0565b01905f5b828110612fcf57505050565b806060602080938501015201612fc3565b6020818303126103935780519067ffffffffffffffff8211610393570181601f82011215610393578051613013816105f7565b926130216040519485610574565b81845260208284010111610393576106649160208085019101610f7b565b949096939561304c613256565b60ff61086b5460e01c16610c66576130676101408701612944565b63ffffffff429116101580613126575b610c1e576130853687612958565b61308e90613918565b97613097610596565b986130a23689612958565b8a5260208a0152604089018490526001600160a01b03851660608a01526130ca36848a610613565b60808a015260a08901526130dd8661294e565b966130eb6101008801612944565b9236906130f792610613565b94369061310392610613565b9460e00135906131129661403c565b3361311c91613a6b565b6103f36001606555565b506131336040870161294e565b6001600160a01b0316331415613077565b73420000000000000000000000000000000000000780330361322c576020600491604051928380927f6e296e450000000000000000000000000000000000000000000000000000000082525afa908115611b19575f916131fd575b506001600160a01b036131ca6131be610869546001600160a01b031690565b6001600160a01b031690565b9116036131d357565b60046040517f36a816d9000000000000000000000000000000000000000000000000000000008152fd5b61321f915060203d602011613225575b6132178183610574565b8101906142c4565b5f61319f565b503d61320d565b60046040517f4a74df92000000000000000000000000000000000000000000000000000000008152fd5b600260655414610393576002606555565b92936106649695919294610140956001600160a01b0380951686525f60208701526040860152606085015263ffffffff809116608085015260a08401525f60c08401521660e08201525f610100820152816101208201520190610f9c565b91959693949290926132f36119a561199e886119918b6001600160a01b03165f5261086d60205260405f2090565b611c5b5760070b936706f05b59d3b2000061330d866142d9565b10156134dc576ec097ce7bc90715b34b9f100000000082116134b25763ffffffff9361333b858a1642612e6a565b857f00000000000000000000000000000000000000000000000000000000000000001610611c315761086b5460c01c63ffffffff16986133a061337d8b612e8f565b61086b9063ffffffff60c01b1963ffffffff60c01b83549260c01b169116179055565b6001600160a01b0395867f00000000000000000000000000000000000000000000000000000000000000001694878b16868114806134a9575b1561346c5750803403611b1e57853b15610393575f60049660405197888092630d0e30db60e41b825234905af18015611b19577fa123dc29aebf7d0c3322c8eeb5b999e859f39937950ed31056532713d0de396f996134549761344392613459575b505b826142e8565b91604051988998169c169a87613267565b0390a4565b80611b0d613466926104f0565b5f61343b565b61345496507fa123dc29aebf7d0c3322c8eeb5b999e859f39937950ed31056532713d0de396f996134a4836134439330903390614142565b61343d565b503415156133d9565b60046040517fc45b6b52000000000000000000000000000000000000000000000000000000008152fd5b60046040517fa13c425c000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169116811461353d575b50565b476135455750565b4790803b15610393575f90600460405180948193630d0e30db60e41b83525af18015611b19571561353a576103f3906104f0565b9081518082526020808093019301915f5b828110613598575050505090565b83516001600160a01b03168552938101939281019260010161358a565b6040805160208082018181528551838501528186015160608401529285015160c0608084015280516101008401819052610120840198979692918201915f5b82811061366157505050508161364a610664979860a08461362460606136589701518387019063ffffffff169052565b60808101516001600160a01b031660c08601520151838203603f190160e0850152613579565b03601f198101835282610574565b5190209161431e565b83518b5299810199928101926001016135f4565b613680600291612650565b500162ffffff8260081c16805f5281602052600160ff60405f205494161b80809416146136b8575f5260205260405f20908154179055565b60046040517f954476d9000000000000000000000000000000000000000000000000000000008152fd5b92949391909380518251036137b0578151915f5b83811061376257505050508261370d575b50505050565b6001600160a01b03816137417f828fc203220356df8f072a91681caee7d5c75095e2a95e80ed5a14b384697f7193866143cb565b6040805195865233602087015291169463ffffffff1693a45f808080613707565b8061376f60019284612a6b565b518061377d575b50016136f6565b6137aa9061379b61378e8488612a6b565b516001600160a01b031690565b6001600160a01b03891661436f565b5f613776565b60046040517fcd298b38000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b031680156138225761086a816001600160a01b03198254161790557f1f17a88f67b0f49060a34bec1a4723a563620e6aa265eb640b5046dcee0759a05f80a2565b60046040517f2d234e48000000000000000000000000000000000000000000000000000000008152fd5b80516001600160a01b0316825261066491610180906020838101516001600160a01b0316908201526040838101516001600160a01b0316908201526060838101516001600160a01b0316908201526080838101516001600160a01b03169082015260a083015160a082015260c083015160c082015260e083015160e08201526138e3610100808501519083019063ffffffff169052565b6101208381015163ffffffff16908201526101408381015163ffffffff16908201528161016080940151938201520190610f9c565b60405161394981613935602082019460408652606083019061384c565b46604083015203601f198101835282610574565b51902090565b61395882612f20565b52565b906001600160a01b0382511681526060806139856020850151608060208601526080850190610f9c565b936040810151604085015201519161399c83612f20565b015290565b9a97909695613a1f966106649d9b9660808e613a0e98613a2e9e986101809d6001600160a01b03998a80921685521660208401526040830152606082015201528c60a063ffffffff8094169101521660c08c01521660e08a01526101008901906001600160a01b03169052565b6001600160a01b0316610120870152565b80610140860152840190610f9c565b9161016081840391015261395b565b9061066494936080936001600160a01b03809316845260208401521660408201528160608201520190610f9c565b805191610120830190613a82825163ffffffff1690565b63ffffffff42911610613d655760208301516001613aa9825f5261087260205260405f2090565b5403613d5e576001905b6002613ac8825f5261087260205260405f2090565b5414613d3457613ae1905f5261087260205260405f2090565b6002905560608501516001600160a01b031660808601516001600160a01b03169260a0870151918660c0890151948960a08301519660e082015197610100830151613b2f9063ffffffff1690565b9a5163ffffffff1661014084015163ffffffff16906040850151613b59906001600160a01b031690565b928551613b6c906001600160a01b031690565b946020870151613b82906001600160a01b031690565b9661016001519760608a0151613b9e906001600160a01b031690565b996080810151906040015190613bb26105d7565b6001600160a01b03909c168c5260208c015260408b0152613bd69060608b0161394f565b6040519b6001600160a01b038d9c169f63ffffffff169e613bf79b8d6139a1565b037f571749edf1d5c9599318cdbc4e28a6475d65e87fd3b2ddbe1e9a8d5e7a0f0ff791a460608101516001600160a01b031691829033821480613d2c575b61370757608001516001600160a01b03169260806040840151936001600160a01b03861685856001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001683145f14613d1c5750613c9b9130903390614142565b613ca5858461476e565b0151913b151580613d12575b613cbb5750505050565b803b1561039357613ce8935f809460405196879586948593633a5be8cb60e01b8552339160048601613a3d565b03925af18015611b1957613cff575b808080613707565b80611b0d613d0c926104f0565b5f613cf7565b5081511515613cb1565b613d27923390614142565b613ca5565b506001613c35565b60046040517f8f260c60000000000000000000000000000000000000000000000000000000008152fd5b5f90613ab3565b600460405163d642b7d960e01b8152fd5b905f82516101208101613d8d815163ffffffff1690565b63ffffffff42911610613d655760208501516002613db4825f5261087260205260405f2090565b5414613d3457613dcd905f5261087260205260405f2090565b6002905560608201516001600160a01b031660808301516001600160a01b03169060a08401519260c0850151918860a0810151938760e081015195610100820151613e1b9063ffffffff1690565b955163ffffffff1661014083015163ffffffff1660408401516001600160a01b0316918451613e50906001600160a01b031690565b936020860151613e66906001600160a01b031690565b956101600151966060890151613e82906001600160a01b031690565b986080810151906040015190613e966105d7565b6001600160a01b03909b168b5260208b015260408a0152600260608a01526040519d63ffffffff8f9c169d613ecb9b8d6139a1565b037f571749edf1d5c9599318cdbc4e28a6475d65e87fd3b2ddbe1e9a8d5e7a0f0ff7905f94a460608401516001600160a01b0316906001600160a01b03948583169182331480614026575b61401d57608001516001600160a01b03169060408101519687818416917f00000000000000000000000000000000000000000000000000000000000000001682145f1461400657906080929187613ff2575b613f7391508561476e565b0151923b151580613fe8575b613f8c575b505050509050565b813b15613fe45783613fb8959660405196879586948593633a5be8cb60e01b8552339160048601613a3d565b03925af18015611b1957613fd1575b8080808493613f84565b80611b0d613fde926104f0565b5f613fc7565b8380fd5b5082511515613f7f565b613fff9130903390614142565b5f88613f68565b60809291965061401890865f9861436f565b613f73565b50505050509050565b505f613f16565b90816020910312610393575190565b93926042936001600160a01b036103f3989760208151910120916040519363ffffffff60208601967f152eb71524aef34d838ab76573c14b1ebfa5e385d9ab29d7cf5398daa2438bd9885216604086015286606086015260808501521660a083015260c082015260c081526140b08161053c565b5190209061047f549061048054906040519160208301937fc2f8787176b8ac6bf7215b4adcc1e069bf4ab82d9ab1df05a57a91d425935b6e85526040840152606083015260808201526080815261410681610558565b51902090604051917f1901000000000000000000000000000000000000000000000000000000000000835260028301526022820152209061498b565b90926103f393604051937f23b872dd0000000000000000000000000000000000000000000000000000000060208601526001600160a01b03809216602486015216604484015260648301526064825261419a82610558565b614a9a565b60ff5f5460081c161561039357565b60ff5f5460081c1615610393576001606555565b6001600160a01b0316801561420a57610869816001600160a01b03198254161790557fa9e8c42c9e7fca7f62755189a16b2f5314d43d8fb24e91ba54e6d65f9314e8495f80a2565b60046040517fba97b39d000000000000000000000000000000000000000000000000000000008152fd5b916119a5906142ad9284516040809601519186519161425283610504565b825261365861426d6020840192468452898501958652612650565b50549388519283916142926020840196602088525160608d86015260a085019061384c565b9151606084015251608083015203601f198101835282610574565b6142b45750565b6004905163582f497d60e11b8152fd5b908160209103126103935751610664816103d7565b5f81126142e35790565b5f0390565b90670de0b6b3a7640000915f828403921283831281169084841390151617612c3a57818102918183041490151715612c3a570490565b929091905f915b8451831015614367576143388386612a6b565b519081811015614356575f52602052600160405f205b920191614325565b905f52602052600160405f2061434e565b915092501490565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000060208201526001600160a01b03909216602483015260448201929092526103f39161419a82606481015b03601f198101845283610574565b906001600160a01b0390818116907f0000000000000000000000000000000000000000000000000000000000000000831682036144fc5750803b15610393575f6040518092632e1a7d4d60e01b825281838161442f89600483019190602083019252565b03925af18015611b19576144e9575b50610c5a549161445761086a546001600160a01b031690565b73420000000000000000000000000000000000001090813b1561039357604051631474f2a960e31b8152602086901c949094166001600160a01b0390811660048601521660248401526044830182905263ffffffff909316606483015260a060848301525f60a483018190529192839160c4918391905af18015611b19576144dc5750565b80611b0d6103f3926104f0565b80611b0d6144f6926104f0565b5f61443e565b91807f000000000000000000000000000000000000000000000000000000000000000016151580614743575b1561454c575050506103f39061454761086a546001600160a01b031690565b614c20565b8061457961456c856001600160a01b03165f52610c5c60205260405f2090565b546001600160a01b031690565b1661471f577342000000000000000000000000000000000000105b16906145b86131be61456c856001600160a01b03165f52610c5d60205260405f2090565b156146995783826145c892614b2a565b6145e761456c836001600160a01b03165f52610c5d60205260405f2090565b906145fb61086a546001600160a01b031690565b9161460c610c5a5463ffffffff1690565b823b15610393576040517f4823f1140000000000000000000000000000000000000000000000000000000081526001600160a01b0395861660048201529185166024830152929093166044840152606483019390935263ffffffff16608482015260c060a48201525f60c482018190529091829081838160e481015b03925af18015611b19576144dc5750565b50916146ae61086a546001600160a01b031690565b926146bf610c5a5463ffffffff1690565b93813b15610393575f809461468860405197889687958694631474f2a960e31b8652600486019260c0949163ffffffff936001600160a01b038092168652166020850152604084015216606082015260a060808201525f60a08201520190565b61473e61456c846001600160a01b03165f52610c5c60205260405f2090565b614594565b50807f0000000000000000000000000000000000000000000000000000000000000000168214614528565b6001600160a01b0390811690813b156147ae57906103f392917f00000000000000000000000000000000000000000000000000000000000000001661436f565b7f000000000000000000000000000000000000000000000000000000000000000016803b15610393575f8091602460405180948193632e1a7d4d60e01b83528860048401525af18015611b1957614820575b50814710610393575f80809381935af1614818612aa3565b501561039357565b614829906104f0565b5f614800565b61483881614948565b6001600160a01b0381167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a28151158015906148f0575b614879575050565b5f8061353a937f206661696c656400000000000000000000000000000000000000000000000000604080516148ad81610504565b602781527f416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c60208201520152602081519101845af46148ea612aa3565b91614e8f565b505f614871565b61490081614948565b6001600160a01b0381167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a281511580159061494057614879575050565b506001614871565b803b15610393576001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc91166001600160a01b0319825416179055565b6149958383614e5e565b6005819592951015612f2a57159384614a84575b5083156149e5575b505050156149bb57565b60046040517f938a1821000000000000000000000000000000000000000000000000000000008152fd5b5f929350908291604051614a368161364a60208201947f1626ba7e00000000000000000000000000000000000000000000000000000000998a87526024840152604060448401526064830190610f9c565b51915afa90614a43612aa3565b82614a76575b82614a59575b50505f80806149b1565b614a6e9192506020808251830101910161402d565b145f80614a4f565b915060208251101591614a49565b6001600160a01b0383811691161493505f6149a9565b905f806001600160a01b03614af19416927f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65646020604051614ada816104cf565b818152015260208151910182855af16148ea612aa3565b8051908115918215614b07575b50501561039357565b81925090602091810103126103935760200151614b2381610a18565b5f80614afe565b6044919260206001600160a01b03604051948580927fdd62ed3e000000000000000000000000000000000000000000000000000000008252306004830152808916602483015286165afa928315611b19575f93614bdf575b508201809211612c3a576040517f095ea7b30000000000000000000000000000000000000000000000000000000060208201526001600160a01b03909316602484015260448301919091526103f3919061419a82606481016143bd565b614bf991935060203d602011610da257610d938183610574565b915f614b82565b90816020910312610393575167ffffffffffffffff811681036103935790565b7f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b0392837f00000000000000000000000000000000000000000000000000000000000000001691614c7a828486614b2a565b604092604051937fcb75c11c0000000000000000000000000000000000000000000000000000000085526020936004908587600481875afa978815611b195789975f99614e37575b506040517fa56ec6320000000000000000000000000000000000000000000000000000000081526001600160a01b03918916918216600482015299909887918b9190829081602481015b0392165afa988915611b19575f99614e18575b509390951696947f000000000000000000000000000000000000000000000000000000000000000093805b614d5957505050505050505050565b614dc39087811115614e125787905b84517f6fd3504e00000000000000000000000000000000000000000000000000000000815284810183815263ffffffff89166020820152604081018d90526001600160a01b038c166060820152909389918591829160800190565b03815f8a5af1928315611b1957614ddf93614de5575b50612e6a565b80614d4a565b614e0490893d8b11614e0b575b614dfc8183610574565b810190614c00565b505f614dd9565b503d614df2565b80614d68565b614e30919950863d8811610da257610d938183610574565b975f614d1f565b8791995088614e55614d0c92843d8611613225576132178183610574565b9a925050614cc2565b9060418151145f14614e8657610f7791602082015190606060408401519301515f1a90614eb8565b50505f90600290565b9015614ea957815115614ea0575090565b3b156103935790565b50805190811561039357602001fd5b7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411614f28576020935f9360ff60809460405194855216868401526040830152606082015282805260015afa15611b19575f516001600160a01b03811615614f2057905f90565b505f90600190565b505050505f9060039056fea264697066735822122035969690dfae13a9296c07a3d239e9de928b72312fdb262110454a86aed04fcb64736f6c63430008170033", diff --git a/package.json b/package.json index f3249a50a..9d3d815cd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@across-protocol/contracts", - "version": "3.0.9", + "version": "3.0.10", "author": "UMA Team", "license": "AGPL-3.0-only", "repository": {