From 72ecb1b3d1e6778d89a5c7f7a1ce2c1e8de819b6 Mon Sep 17 00:00:00 2001 From: Michal Mironczuk Date: Mon, 24 Feb 2025 19:42:41 +0100 Subject: [PATCH] Added contract verification check --- output.log | 5102 ++++++++++++++++++ script/deploy/verifyNetworkDeploymentLogs.ts | 23 +- 2 files changed, 5116 insertions(+), 9 deletions(-) create mode 100644 output.log diff --git a/output.log b/output.log new file mode 100644 index 000000000..ce282dddc --- /dev/null +++ b/output.log @@ -0,0 +1,5102 @@ +Initializing... | Deployment logs loaded for MAINNET. ✔ +Checking LiFiDiamond contract deployment... | Checking LiFiDiamond contract deployment... / Checking LiFiDiamond contract deployment... - LiFiDiamond contract is deployed. ✔ +Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - Verifying on-chain facets against deploy log... \ Verifying on-chain facets against deploy log... | Verifying on-chain facets against deploy log... / Verifying on-chain facets against deploy log... - On-chain facets verification complete. ✔ +Verifying potential missing entries on-chain... - Missing on-chain entries verification complete. ✔ +Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \unknown +0xf7993a8df974ad022647e63402d6315137c58abf +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror TokenAddressIsZero();\\nerror TokenNotSupported();\\nerror CannotBridgeToSameNetwork();\\nerror ZeroPostSwapBalance();\\nerror NoSwapDataProvided();\\nerror NativeValueWithERC();\\nerror ContractCallNotAllowed();\\nerror NullAddrIsNotAValidSpender();\\nerror NullAddrIsNotAnERC20Token();\\nerror NoTransferToNullAddress();\\nerror NativeAssetTransferFailed();\\nerror InvalidBridgeConfigLength();\\nerror InvalidAmount();\\nerror InvalidContract();\\nerror InvalidConfig();\\nerror UnsupportedChainId(uint256 chainId);\\nerror InvalidReceiver();\\nerror InvalidDestinationChain();\\nerror InvalidSendingToken();\\nerror InvalidCaller();\\nerror AlreadyInitialized();\\nerror NotInitialized();\\nerror OnlyContractOwner();\\nerror CannotAuthoriseSelf();\\nerror RecoveryAddressCannotBeZero();\\nerror CannotDepositNativeToken();\\nerror InvalidCallData();\\nerror NativeAssetNotSupported();\\nerror UnAuthorized();\\nerror NoSwapFromZeroBalance();\\nerror InvalidFallbackAddress();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror ZeroAmount();\\nerror InvalidFee();\\nerror InformationMismatch();\\nerror NotAContract();\\nerror NotEnoughBalance(uint256 requested, uint256 available);\\n\"\r\n },\r\n \"src/Facets/DiamondCutFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\n\\ncontract DiamondCutFacet is IDiamondCut {\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external override {\\n LibDiamond.enforceIsContractOwner();\\n LibDiamond.diamondCut(_diamondCut, _init, _calldata);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n error UintOutOfBounds();\\n\\n // -------------------------\\n\\n function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) {\\n bytes memory tempBytes;\\n\\n assembly {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // Store the length of the first bytes array at the beginning of\\n // the memory for tempBytes.\\n let length := mload(_preBytes)\\n mstore(tempBytes, length)\\n\\n // Maintain a memory counter for the current write location in the\\n // temp bytes array by adding the 32 bytes for the array length to\\n // the starting location.\\n let mc := add(tempBytes, 0x20)\\n // Stop copying when the memory counter reaches the length of the\\n // first bytes array.\\n let end := add(mc, length)\\n\\n for {\\n // Initialize a copy counter to the start of the _preBytes data,\\n // 32 bytes into its memory.\\n let cc := add(_preBytes, 0x20)\\n } lt(mc, end) {\\n // Increase both counters by 32 bytes each iteration.\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n // Write the _preBytes data into the tempBytes memory 32 bytes\\n // at a time.\\n mstore(mc, mload(cc))\\n }\\n\\n // Add the length of _postBytes to the current length of tempBytes\\n // and store it as the new length in the first 32 bytes of the\\n // tempBytes memory.\\n length := mload(_postBytes)\\n mstore(tempBytes, add(length, mload(tempBytes)))\\n\\n // Move the memory counter back from a multiple of 0x20 to the\\n // actual end of the _preBytes data.\\n mc := end\\n // Stop copying when the memory counter reaches the new combined\\n // length of the arrays.\\n end := add(mc, length)\\n\\n for {\\n let cc := add(_postBytes, 0x20)\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n // Update the free-memory pointer by padding our last write location\\n // to 32 bytes: add 31 bytes to the end of tempBytes to move to the\\n // next 32 byte block, then round down to the nearest multiple of\\n // 32. If the sum of the length of the two arrays is zero then add\\n // one before rounding down to leave a blank 32 bytes (the length block with 0).\\n mstore(\\n 0x40,\\n and(\\n add(add(end, iszero(add(length, mload(_preBytes)))), 31),\\n not(31) // Round down to the nearest 32 bytes.\\n )\\n )\\n }\\n\\n return tempBytes;\\n }\\n\\n function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {\\n assembly {\\n // Read the first 32 bytes of _preBytes storage, which is the length\\n // of the array. (We don't need to use the offset into the slot\\n // because arrays use the entire slot.)\\n let fslot := sload(_preBytes.slot)\\n // Arrays of 31 bytes or less have an even value in their slot,\\n // while longer arrays have an odd value. The actual length is\\n // the slot divided by two for odd values, and the lowest order\\n // byte divided by two for even values.\\n // If the slot is even, bitwise and the slot with 255 and divide by\\n // two to get the length. If the slot is odd, bitwise and the slot\\n // with -1 and divide by two.\\n let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\\n let mlength := mload(_postBytes)\\n let newlength := add(slength, mlength)\\n // slength can contain both the length and contents of the array\\n // if length < 32 bytes so let's prepare for that\\n // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\\n switch add(lt(slength, 32), lt(newlength, 32))\\n case 2 {\\n // Since the new array still fits in the slot, we just need to\\n // update the contents of the slot.\\n // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length\\n sstore(\\n _preBytes.slot,\\n // all the modifications to the slot are inside this\\n // next block\\n add(\\n // we can just add to the slot contents because the\\n // bytes we want to change are the LSBs\\n fslot,\\n add(\\n mul(\\n div(\\n // load the bytes from memory\\n mload(add(_postBytes, 0x20)),\\n // zero all bytes to the right\\n exp(0x100, sub(32, mlength))\\n ),\\n // and now shift left the number of bytes to\\n // leave space for the length in the slot\\n exp(0x100, sub(32, newlength))\\n ),\\n // increase length by the double of the memory\\n // bytes length\\n mul(mlength, 2)\\n )\\n )\\n )\\n }\\n case 1 {\\n // The stored value fits in the slot, but the combined value\\n // will exceed it.\\n // get the keccak hash to get the contents of the array\\n mstore(0x0, _preBytes.slot)\\n let sc := add(keccak256(0x0, 0x20), div(slength, 32))\\n\\n // save new length\\n sstore(_preBytes.slot, add(mul(newlength, 2), 1))\\n\\n // The contents of the _postBytes array start 32 bytes into\\n // the structure. Our first read should obtain the `submod`\\n // bytes that can fit into the unused space in the last word\\n // of the stored array. To get this, we read 32 bytes starting\\n // from `submod`, so the data we read overlaps with the array\\n // contents by `submod` bytes. Masking the lowest-order\\n // `submod` bytes allows us to add that value directly to the\\n // stored value.\\n\\n let submod := sub(32, slength)\\n let mc := add(_postBytes, submod)\\n let end := add(_postBytes, mlength)\\n let mask := sub(exp(0x100, submod), 1)\\n\\n sstore(\\n sc,\\n add(\\n and(fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00),\\n and(mload(mc), mask)\\n )\\n )\\n\\n for {\\n mc := add(mc, 0x20)\\n sc := add(sc, 1)\\n } lt(mc, end) {\\n sc := add(sc, 1)\\n mc := add(mc, 0x20)\\n } {\\n sstore(sc, mload(mc))\\n }\\n\\n mask := exp(0x100, sub(mc, end))\\n\\n sstore(sc, mul(div(mload(mc), mask), mask))\\n }\\n default {\\n // get the keccak hash to get the contents of the array\\n mstore(0x0, _preBytes.slot)\\n // Start copying to the last used word of the stored array.\\n let sc := add(keccak256(0x0, 0x20), div(slength, 32))\\n\\n // save new length\\n sstore(_preBytes.slot, add(mul(newlength, 2), 1))\\n\\n // Copy over the first `submod` bytes of the new data as in\\n // case 1 above.\\n let slengthmod := mod(slength, 32)\\n let submod := sub(32, slengthmod)\\n let mc := add(_postBytes, submod)\\n let end := add(_postBytes, mlength)\\n let mask := sub(exp(0x100, submod), 1)\\n\\n sstore(sc, add(sload(sc), and(mload(mc), mask)))\\n\\n for {\\n sc := add(sc, 1)\\n mc := add(mc, 0x20)\\n } lt(mc, end) {\\n sc := add(sc, 1)\\n mc := add(mc, 0x20)\\n } {\\n sstore(sc, mload(mc))\\n }\\n\\n mask := exp(0x100, sub(mc, end))\\n\\n sstore(sc, mul(div(mload(mc), mask), mask))\\n }\\n }\\n }\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\\n }\\n\\n return tempAddress;\\n }\\n\\n function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {\\n if (_bytes.length < _start + 1) {\\n revert UintOutOfBounds();\\n }\\n uint8 tempUint;\\n\\n assembly {\\n tempUint := mload(add(add(_bytes, 0x1), _start))\\n }\\n\\n return tempUint;\\n }\\n\\n function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {\\n if (_bytes.length < _start + 2) {\\n revert UintOutOfBounds();\\n }\\n uint16 tempUint;\\n\\n assembly {\\n tempUint := mload(add(add(_bytes, 0x2), _start))\\n }\\n\\n return tempUint;\\n }\\n\\n function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {\\n if (_bytes.length < _start + 4) {\\n revert UintOutOfBounds();\\n }\\n uint32 tempUint;\\n\\n assembly {\\n tempUint := mload(add(add(_bytes, 0x4), _start))\\n }\\n\\n return tempUint;\\n }\\n\\n function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {\\n if (_bytes.length < _start + 8) {\\n revert UintOutOfBounds();\\n }\\n uint64 tempUint;\\n\\n assembly {\\n tempUint := mload(add(add(_bytes, 0x8), _start))\\n }\\n\\n return tempUint;\\n }\\n\\n function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {\\n if (_bytes.length < _start + 12) {\\n revert UintOutOfBounds();\\n }\\n uint96 tempUint;\\n\\n assembly {\\n tempUint := mload(add(add(_bytes, 0xc), _start))\\n }\\n\\n return tempUint;\\n }\\n\\n function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {\\n if (_bytes.length < _start + 16) {\\n revert UintOutOfBounds();\\n }\\n uint128 tempUint;\\n\\n assembly {\\n tempUint := mload(add(add(_bytes, 0x10), _start))\\n }\\n\\n return tempUint;\\n }\\n\\n function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {\\n if (_bytes.length < _start + 32) {\\n revert UintOutOfBounds();\\n }\\n uint256 tempUint;\\n\\n assembly {\\n tempUint := mload(add(add(_bytes, 0x20), _start))\\n }\\n\\n return tempUint;\\n }\\n\\n function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {\\n if (_bytes.length < _start + 32) {\\n revert UintOutOfBounds();\\n }\\n bytes32 tempBytes32;\\n\\n assembly {\\n tempBytes32 := mload(add(add(_bytes, 0x20), _start))\\n }\\n\\n return tempBytes32;\\n }\\n\\n function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {\\n bool success = true;\\n\\n assembly {\\n let length := mload(_preBytes)\\n\\n // if lengths don't match the arrays are not equal\\n switch eq(length, mload(_postBytes))\\n case 1 {\\n // cb is a circuit breaker in the for loop since there's\\n // no said feature for inline assembly loops\\n // cb = 1 - don't breaker\\n // cb = 0 - break\\n let cb := 1\\n\\n let mc := add(_preBytes, 0x20)\\n let end := add(mc, length)\\n\\n for {\\n let cc := add(_postBytes, 0x20)\\n // the next line is the loop condition:\\n // while(uint256(mc < end) + cb == 2)\\n } eq(add(lt(mc, end), cb), 2) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n // if any of these checks fails then arrays are not equal\\n if iszero(eq(mload(mc), mload(cc))) {\\n // unsuccess:\\n success := 0\\n cb := 0\\n }\\n }\\n }\\n default {\\n // unsuccess:\\n success := 0\\n }\\n }\\n\\n return success;\\n }\\n\\n function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) {\\n bool success = true;\\n\\n assembly {\\n // we know _preBytes_offset is 0\\n let fslot := sload(_preBytes.slot)\\n // Decode the length of the stored array like in concatStorage().\\n let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\\n let mlength := mload(_postBytes)\\n\\n // if lengths don't match the arrays are not equal\\n switch eq(slength, mlength)\\n case 1 {\\n // slength can contain both the length and contents of the array\\n // if length < 32 bytes so let's prepare for that\\n // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\\n if iszero(iszero(slength)) {\\n switch lt(slength, 32)\\n case 1 {\\n // blank the last byte which is the length\\n fslot := mul(div(fslot, 0x100), 0x100)\\n\\n if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {\\n // unsuccess:\\n success := 0\\n }\\n }\\n default {\\n // cb is a circuit breaker in the for loop since there's\\n // no said feature for inline assembly loops\\n // cb = 1 - don't breaker\\n // cb = 0 - break\\n let cb := 1\\n\\n // get the keccak hash to get the contents of the array\\n mstore(0x0, _preBytes.slot)\\n let sc := keccak256(0x0, 0x20)\\n\\n let mc := add(_postBytes, 0x20)\\n let end := add(mc, mlength)\\n\\n // the next line is the loop condition:\\n // while(uint256(mc < end) + cb == 2)\\n // solhint-disable-next-line no-empty-blocks\\n for {\\n\\n } eq(add(lt(mc, end), cb), 2) {\\n sc := add(sc, 1)\\n mc := add(mc, 0x20)\\n } {\\n if iszero(eq(sload(sc), mload(mc))) {\\n // unsuccess:\\n success := 0\\n cb := 0\\n }\\n }\\n }\\n }\\n }\\n default {\\n // unsuccess:\\n success := 0\\n }\\n }\\n\\n return success;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION = keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner) revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(bytes memory _res) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@axelar-network/=node_modules/@axelar-network/\",\r\n \"@connext/=node_modules/@connext/\",\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=node_modules/@openzeppelin/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"solmate/=lib/solmate/src/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 10000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[],\"name\":\"CalldataEmptyButInitNotZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FacetAddressIsNotZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FacetAddressIsZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FacetContainsNoCode\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FunctionAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FunctionDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FunctionIsImmutable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectFacetCutAction\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InitReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InitZeroButCalldataNotEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSelectorsInFace\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyContractOwner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"indexed\":false,\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"_diamondCut\",\"type\":\"tuple[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_init\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"_calldata\",\"type\":\"bytes\"}],\"name\":\"DiamondCut\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"_diamondCut\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"_init\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_calldata\",\"type\":\"bytes\"}],\"name\":\"diamondCut\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ContractName: "DiamondCutFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "10000", + ConstructorArguments: "", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror TokenAddressIsZero();\nerror TokenNotSupported();\nerror CannotBridgeToSameNetwork();\nerror ZeroPostSwapBalance();\nerror NoSwapDataProvided();\nerror NativeValueWithERC();\nerror ContractCallNotAllowed();\nerror NullAddrIsNotAValidSpender();\nerror NullAddrIsNotAnERC20Token();\nerror NoTransferToNullAddress();\nerror NativeAssetTransferFailed();\nerror InvalidBridgeConfigLength();\nerror InvalidAmount();\nerror InvalidContract();\nerror InvalidConfig();\nerror UnsupportedChainId(uint256 chainId);\nerror InvalidReceiver();\nerror InvalidDestinationChain();\nerror InvalidSendingToken();\nerror InvalidCaller();\nerror AlreadyInitialized();\nerror NotInitialized();\nerror OnlyContractOwner();\nerror CannotAuthoriseSelf();\nerror RecoveryAddressCannotBeZero();\nerror CannotDepositNativeToken();\nerror InvalidCallData();\nerror NativeAssetNotSupported();\nerror UnAuthorized();\nerror NoSwapFromZeroBalance();\nerror InvalidFallbackAddress();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror ZeroAmount();\nerror InvalidFee();\nerror InformationMismatch();\nerror NotAContract();\nerror NotEnoughBalance(uint256 requested, uint256 available);\n" + }, + "src/Facets/DiamondCutFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\n\ncontract DiamondCutFacet is IDiamondCut {\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external override {\n LibDiamond.enforceIsContractOwner();\n LibDiamond.diamondCut(_diamondCut, _init, _calldata);\n }\n}\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n error UintOutOfBounds();\n\n // -------------------------\n\n function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) {\n bytes memory tempBytes;\n\n assembly {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // Store the length of the first bytes array at the beginning of\n // the memory for tempBytes.\n let length := mload(_preBytes)\n mstore(tempBytes, length)\n\n // Maintain a memory counter for the current write location in the\n // temp bytes array by adding the 32 bytes for the array length to\n // the starting location.\n let mc := add(tempBytes, 0x20)\n // Stop copying when the memory counter reaches the length of the\n // first bytes array.\n let end := add(mc, length)\n\n for {\n // Initialize a copy counter to the start of the _preBytes data,\n // 32 bytes into its memory.\n let cc := add(_preBytes, 0x20)\n } lt(mc, end) {\n // Increase both counters by 32 bytes each iteration.\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n // Write the _preBytes data into the tempBytes memory 32 bytes\n // at a time.\n mstore(mc, mload(cc))\n }\n\n // Add the length of _postBytes to the current length of tempBytes\n // and store it as the new length in the first 32 bytes of the\n // tempBytes memory.\n length := mload(_postBytes)\n mstore(tempBytes, add(length, mload(tempBytes)))\n\n // Move the memory counter back from a multiple of 0x20 to the\n // actual end of the _preBytes data.\n mc := end\n // Stop copying when the memory counter reaches the new combined\n // length of the arrays.\n end := add(mc, length)\n\n for {\n let cc := add(_postBytes, 0x20)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n // Update the free-memory pointer by padding our last write location\n // to 32 bytes: add 31 bytes to the end of tempBytes to move to the\n // next 32 byte block, then round down to the nearest multiple of\n // 32. If the sum of the length of the two arrays is zero then add\n // one before rounding down to leave a blank 32 bytes (the length block with 0).\n mstore(\n 0x40,\n and(\n add(add(end, iszero(add(length, mload(_preBytes)))), 31),\n not(31) // Round down to the nearest 32 bytes.\n )\n )\n }\n\n return tempBytes;\n }\n\n function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {\n assembly {\n // Read the first 32 bytes of _preBytes storage, which is the length\n // of the array. (We don't need to use the offset into the slot\n // because arrays use the entire slot.)\n let fslot := sload(_preBytes.slot)\n // Arrays of 31 bytes or less have an even value in their slot,\n // while longer arrays have an odd value. The actual length is\n // the slot divided by two for odd values, and the lowest order\n // byte divided by two for even values.\n // If the slot is even, bitwise and the slot with 255 and divide by\n // two to get the length. If the slot is odd, bitwise and the slot\n // with -1 and divide by two.\n let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n let mlength := mload(_postBytes)\n let newlength := add(slength, mlength)\n // slength can contain both the length and contents of the array\n // if length < 32 bytes so let's prepare for that\n // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n switch add(lt(slength, 32), lt(newlength, 32))\n case 2 {\n // Since the new array still fits in the slot, we just need to\n // update the contents of the slot.\n // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length\n sstore(\n _preBytes.slot,\n // all the modifications to the slot are inside this\n // next block\n add(\n // we can just add to the slot contents because the\n // bytes we want to change are the LSBs\n fslot,\n add(\n mul(\n div(\n // load the bytes from memory\n mload(add(_postBytes, 0x20)),\n // zero all bytes to the right\n exp(0x100, sub(32, mlength))\n ),\n // and now shift left the number of bytes to\n // leave space for the length in the slot\n exp(0x100, sub(32, newlength))\n ),\n // increase length by the double of the memory\n // bytes length\n mul(mlength, 2)\n )\n )\n )\n }\n case 1 {\n // The stored value fits in the slot, but the combined value\n // will exceed it.\n // get the keccak hash to get the contents of the array\n mstore(0x0, _preBytes.slot)\n let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n // save new length\n sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n // The contents of the _postBytes array start 32 bytes into\n // the structure. Our first read should obtain the `submod`\n // bytes that can fit into the unused space in the last word\n // of the stored array. To get this, we read 32 bytes starting\n // from `submod`, so the data we read overlaps with the array\n // contents by `submod` bytes. Masking the lowest-order\n // `submod` bytes allows us to add that value directly to the\n // stored value.\n\n let submod := sub(32, slength)\n let mc := add(_postBytes, submod)\n let end := add(_postBytes, mlength)\n let mask := sub(exp(0x100, submod), 1)\n\n sstore(\n sc,\n add(\n and(fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00),\n and(mload(mc), mask)\n )\n )\n\n for {\n mc := add(mc, 0x20)\n sc := add(sc, 1)\n } lt(mc, end) {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } {\n sstore(sc, mload(mc))\n }\n\n mask := exp(0x100, sub(mc, end))\n\n sstore(sc, mul(div(mload(mc), mask), mask))\n }\n default {\n // get the keccak hash to get the contents of the array\n mstore(0x0, _preBytes.slot)\n // Start copying to the last used word of the stored array.\n let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n // save new length\n sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n // Copy over the first `submod` bytes of the new data as in\n // case 1 above.\n let slengthmod := mod(slength, 32)\n let submod := sub(32, slengthmod)\n let mc := add(_postBytes, submod)\n let end := add(_postBytes, mlength)\n let mask := sub(exp(0x100, submod), 1)\n\n sstore(sc, add(sload(sc), and(mload(mc), mask)))\n\n for {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } lt(mc, end) {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } {\n sstore(sc, mload(mc))\n }\n\n mask := exp(0x100, sub(mc, end))\n\n sstore(sc, mul(div(mload(mc), mask), mask))\n }\n }\n }\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\n }\n\n return tempAddress;\n }\n\n function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {\n if (_bytes.length < _start + 1) {\n revert UintOutOfBounds();\n }\n uint8 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x1), _start))\n }\n\n return tempUint;\n }\n\n function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {\n if (_bytes.length < _start + 2) {\n revert UintOutOfBounds();\n }\n uint16 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x2), _start))\n }\n\n return tempUint;\n }\n\n function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {\n if (_bytes.length < _start + 4) {\n revert UintOutOfBounds();\n }\n uint32 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x4), _start))\n }\n\n return tempUint;\n }\n\n function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {\n if (_bytes.length < _start + 8) {\n revert UintOutOfBounds();\n }\n uint64 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x8), _start))\n }\n\n return tempUint;\n }\n\n function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {\n if (_bytes.length < _start + 12) {\n revert UintOutOfBounds();\n }\n uint96 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0xc), _start))\n }\n\n return tempUint;\n }\n\n function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {\n if (_bytes.length < _start + 16) {\n revert UintOutOfBounds();\n }\n uint128 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x10), _start))\n }\n\n return tempUint;\n }\n\n function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {\n if (_bytes.length < _start + 32) {\n revert UintOutOfBounds();\n }\n uint256 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x20), _start))\n }\n\n return tempUint;\n }\n\n function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {\n if (_bytes.length < _start + 32) {\n revert UintOutOfBounds();\n }\n bytes32 tempBytes32;\n\n assembly {\n tempBytes32 := mload(add(add(_bytes, 0x20), _start))\n }\n\n return tempBytes32;\n }\n\n function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {\n bool success = true;\n\n assembly {\n let length := mload(_preBytes)\n\n // if lengths don't match the arrays are not equal\n switch eq(length, mload(_postBytes))\n case 1 {\n // cb is a circuit breaker in the for loop since there's\n // no said feature for inline assembly loops\n // cb = 1 - don't breaker\n // cb = 0 - break\n let cb := 1\n\n let mc := add(_preBytes, 0x20)\n let end := add(mc, length)\n\n for {\n let cc := add(_postBytes, 0x20)\n // the next line is the loop condition:\n // while(uint256(mc < end) + cb == 2)\n } eq(add(lt(mc, end), cb), 2) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n // if any of these checks fails then arrays are not equal\n if iszero(eq(mload(mc), mload(cc))) {\n // unsuccess:\n success := 0\n cb := 0\n }\n }\n }\n default {\n // unsuccess:\n success := 0\n }\n }\n\n return success;\n }\n\n function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) {\n bool success = true;\n\n assembly {\n // we know _preBytes_offset is 0\n let fslot := sload(_preBytes.slot)\n // Decode the length of the stored array like in concatStorage().\n let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n let mlength := mload(_postBytes)\n\n // if lengths don't match the arrays are not equal\n switch eq(slength, mlength)\n case 1 {\n // slength can contain both the length and contents of the array\n // if length < 32 bytes so let's prepare for that\n // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n if iszero(iszero(slength)) {\n switch lt(slength, 32)\n case 1 {\n // blank the last byte which is the length\n fslot := mul(div(fslot, 0x100), 0x100)\n\n if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {\n // unsuccess:\n success := 0\n }\n }\n default {\n // cb is a circuit breaker in the for loop since there's\n // no said feature for inline assembly loops\n // cb = 1 - don't breaker\n // cb = 0 - break\n let cb := 1\n\n // get the keccak hash to get the contents of the array\n mstore(0x0, _preBytes.slot)\n let sc := keccak256(0x0, 0x20)\n\n let mc := add(_postBytes, 0x20)\n let end := add(mc, mlength)\n\n // the next line is the loop condition:\n // while(uint256(mc < end) + cb == 2)\n // solhint-disable-next-line no-empty-blocks\n for {\n\n } eq(add(lt(mc, end), cb), 2) {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } {\n if iszero(eq(sload(sc), mload(mc))) {\n // unsuccess:\n success := 0\n cb := 0\n }\n }\n }\n }\n }\n default {\n // unsuccess:\n success := 0\n }\n }\n\n return success;\n }\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION = keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner) revert OnlyContractOwner();\n }\n\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(bytes memory _res) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + } + }, + "settings": { + "remappings": [ + "@axelar-network/=node_modules/@axelar-network/", + "@connext/=node_modules/@connext/", + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=node_modules/@openzeppelin/", + "@uniswap/=node_modules/@uniswap/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "solmate/=lib/solmate/src/" + ], + "optimizer": { + "enabled": true, + "runs": 10000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +null + Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... /OwnershipFacet +0x6faa6906b9e4a59020e673910105567e809789e0 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/OwnershipFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { IERC173 } from \\\"../Interfaces/IERC173.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\n\\n/// @title Ownership Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Manages ownership of the LiFi Diamond contract for admin purposes\\n/// @custom:version 1.0.0\\ncontract OwnershipFacet is IERC173 {\\n /// Storage ///\\n\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.facets.ownership\\\");\\n\\n /// Types ///\\n\\n struct Storage {\\n address newOwner;\\n }\\n\\n /// Errors ///\\n\\n error NoNullOwner();\\n error NewOwnerMustNotBeSelf();\\n error NoPendingOwnershipTransfer();\\n error NotPendingOwner();\\n\\n /// Events ///\\n\\n event OwnershipTransferRequested(\\n address indexed _from,\\n address indexed _to\\n );\\n\\n /// External Methods ///\\n\\n /// @notice Initiates transfer of ownership to a new address\\n /// @param _newOwner the address to transfer ownership to\\n function transferOwnership(address _newOwner) external override {\\n LibDiamond.enforceIsContractOwner();\\n Storage storage s = getStorage();\\n\\n if (LibUtil.isZeroAddress(_newOwner)) revert NoNullOwner();\\n\\n if (_newOwner == LibDiamond.contractOwner())\\n revert NewOwnerMustNotBeSelf();\\n\\n s.newOwner = _newOwner;\\n emit OwnershipTransferRequested(msg.sender, s.newOwner);\\n }\\n\\n /// @notice Cancel transfer of ownership\\n function cancelOwnershipTransfer() external {\\n LibDiamond.enforceIsContractOwner();\\n Storage storage s = getStorage();\\n\\n if (LibUtil.isZeroAddress(s.newOwner))\\n revert NoPendingOwnershipTransfer();\\n s.newOwner = address(0);\\n }\\n\\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\\n function confirmOwnershipTransfer() external {\\n Storage storage s = getStorage();\\n address _pendingOwner = s.newOwner;\\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\\n emit OwnershipTransferred(LibDiamond.contractOwner(), _pendingOwner);\\n LibDiamond.setContractOwner(_pendingOwner);\\n s.newOwner = LibAsset.NULL_ADDRESS;\\n }\\n\\n /// @notice Return the current owner address\\n /// @return owner_ The current owner address\\n function owner() external view override returns (address owner_) {\\n owner_ = LibDiamond.contractOwner();\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function getStorage() private pure returns (Storage storage s) {\\n bytes32 namespace = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n s.slot := namespace\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IERC173.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\n/// @title ERC-173 Contract Ownership Standard\\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\\n/* is ERC165 */\\ninterface IERC173 {\\n /// @dev This emits when ownership of a contract changes.\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n /// @notice Get the address of the owner\\n /// @return owner_ The address of the owner.\\n function owner() external view returns (address owner_);\\n\\n /// @notice Set the address of the new owner of the contract\\n /// @dev Set _newOwner to address(0) to renounce any ownership.\\n /// @param _newOwner The address of the new owner of the contract\\n function transferOwnership(address _newOwner) external;\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[],\"name\":\"NewOwnerMustNotBeSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoNullOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoPendingOwnershipTransfer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotPendingOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyContractOwner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"cancelOwnershipTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"confirmOwnershipTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ContractName: "OwnershipFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/OwnershipFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { IERC173 } from \"../Interfaces/IERC173.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\n\n/// @title Ownership Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Manages ownership of the LiFi Diamond contract for admin purposes\n/// @custom:version 1.0.0\ncontract OwnershipFacet is IERC173 {\n /// Storage ///\n\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.facets.ownership\");\n\n /// Types ///\n\n struct Storage {\n address newOwner;\n }\n\n /// Errors ///\n\n error NoNullOwner();\n error NewOwnerMustNotBeSelf();\n error NoPendingOwnershipTransfer();\n error NotPendingOwner();\n\n /// Events ///\n\n event OwnershipTransferRequested(\n address indexed _from,\n address indexed _to\n );\n\n /// External Methods ///\n\n /// @notice Initiates transfer of ownership to a new address\n /// @param _newOwner the address to transfer ownership to\n function transferOwnership(address _newOwner) external override {\n LibDiamond.enforceIsContractOwner();\n Storage storage s = getStorage();\n\n if (LibUtil.isZeroAddress(_newOwner)) revert NoNullOwner();\n\n if (_newOwner == LibDiamond.contractOwner())\n revert NewOwnerMustNotBeSelf();\n\n s.newOwner = _newOwner;\n emit OwnershipTransferRequested(msg.sender, s.newOwner);\n }\n\n /// @notice Cancel transfer of ownership\n function cancelOwnershipTransfer() external {\n LibDiamond.enforceIsContractOwner();\n Storage storage s = getStorage();\n\n if (LibUtil.isZeroAddress(s.newOwner))\n revert NoPendingOwnershipTransfer();\n s.newOwner = address(0);\n }\n\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\n function confirmOwnershipTransfer() external {\n Storage storage s = getStorage();\n address _pendingOwner = s.newOwner;\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\n emit OwnershipTransferred(LibDiamond.contractOwner(), _pendingOwner);\n LibDiamond.setContractOwner(_pendingOwner);\n s.newOwner = LibAsset.NULL_ADDRESS;\n }\n\n /// @notice Return the current owner address\n /// @return owner_ The current owner address\n function owner() external view override returns (address owner_) {\n owner_ = LibDiamond.contractOwner();\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function getStorage() private pure returns (Storage storage s) {\n bytes32 namespace = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n s.slot := namespace\n }\n }\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Interfaces/IERC173.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\n/// @title ERC-173 Contract Ownership Standard\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\n/* is ERC165 */\ninterface IERC173 {\n /// @dev This emits when ownership of a contract changes.\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n /// @notice Get the address of the owner\n /// @return owner_ The address of the owner.\n function owner() external view returns (address owner_);\n\n /// @notice Set the address of the new owner of the contract\n /// @dev Set _newOwner to address(0) to renounce any ownership.\n /// @param _newOwner The address of the new owner of the contract\n function transferOwnership(address _newOwner) external;\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... |AcrossFacetPacked +0xe397c4883ec89ed4fc9d258f00c689708b2799c9 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/AcrossFacetPacked.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IAcrossSpokePool } from \\\"../Interfaces/IAcrossSpokePool.sol\\\";\\nimport { TransferrableOwnership } from \\\"../Helpers/TransferrableOwnership.sol\\\";\\nimport { AcrossFacet } from \\\"./AcrossFacet.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { ERC20, SafeTransferLib } from \\\"solmate/utils/SafeTransferLib.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { console2 } from \\\"forge-std/console2.sol\\\";\\n\\n/// @title AcrossFacetPacked\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Across in a gas-optimized way\\n/// @custom:version 1.0.0\\ncontract AcrossFacetPacked is ILiFi, TransferrableOwnership {\\n using SafeTransferLib for ERC20;\\n\\n bytes public constant ACROSS_REFERRER_DELIMITER = hex\\\"d00dfeeddeadbeef\\\";\\n uint8 private constant ACROSS_REFERRER_ADDRESS_LENGTH = 20;\\n uint256 private constant REFERRER_OFFSET = 28;\\n\\n /// Storage ///\\n\\n /// @notice The contract address of the cbridge on the source chain.\\n IAcrossSpokePool private immutable spokePool;\\n\\n /// @notice The WETH address on the current chain.\\n address private immutable wrappedNative;\\n\\n /// Events ///\\n\\n event LiFiAcrossTransfer(bytes8 _transactionId);\\n event CallExecutedAndFundsWithdrawn();\\n\\n /// Errors ///\\n\\n error WithdrawFailed();\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract\\n /// @param _spokePool The contract address of the spoke pool on the source chain\\n /// @param _wrappedNative The address of the wrapped native token on the source chain\\n /// @param _owner The address of the contract owner\\n constructor(\\n IAcrossSpokePool _spokePool,\\n address _wrappedNative,\\n address _owner\\n ) TransferrableOwnership(_owner) {\\n spokePool = _spokePool;\\n wrappedNative = _wrappedNative;\\n }\\n\\n /// External Methods ///\\n\\n /// @dev Only meant to be called outside of the context of the diamond\\n /// @notice Sets approval for the Across spoke pool Router to spend the specified token\\n /// @param tokensToApprove The tokens to approve to the Across spoke pool\\n function setApprovalForBridge(\\n address[] calldata tokensToApprove\\n ) external onlyOwner {\\n for (uint256 i; i < tokensToApprove.length; i++) {\\n // Give Across spoke pool approval to pull tokens from this facet\\n LibAsset.maxApproveERC20(\\n IERC20(tokensToApprove[i]),\\n address(spokePool),\\n type(uint256).max\\n );\\n }\\n }\\n\\n /// @notice Bridges native tokens via Across (packed implementation)\\n /// No params, all data will be extracted from manually encoded callData\\n function startBridgeTokensViaAcrossNativePacked() external payable {\\n // calculate end of calldata (and start of delimiter + referrer address)\\n uint256 calldataEndsAt = msg.data.length - REFERRER_OFFSET;\\n\\n // call Across spoke pool to bridge assets\\n spokePool.deposit{ value: msg.value }(\\n address(bytes20(msg.data[12:32])), // receiver\\n wrappedNative, // wrappedNative address\\n msg.value, // minAmount\\n uint64(uint32(bytes4(msg.data[32:36]))), // destinationChainId\\n int64(uint64(bytes8(msg.data[36:44]))), // int64 relayerFeePct\\n uint32(bytes4(msg.data[44:48])), // uint32 quoteTimestamp\\n msg.data[80:calldataEndsAt], // bytes message (due to variable length positioned at the end of the calldata)\\n uint256(bytes32(msg.data[48:80])) // uint256 maxCount\\n );\\n\\n emit LiFiAcrossTransfer(bytes8(msg.data[4:12]));\\n }\\n\\n /// @notice Bridges native tokens via Across (minimal implementation)\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param relayerFeePct The relayer fee in token percentage with 18 decimals\\n /// @param quoteTimestamp The timestamp associated with the suggested fee\\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens\\n /// @param maxCount Used to protect the depositor from frontrunning to guarantee their quote remains valid\\n function startBridgeTokensViaAcrossNativeMin(\\n bytes32 transactionId,\\n address receiver,\\n uint256 destinationChainId,\\n int64 relayerFeePct,\\n uint32 quoteTimestamp,\\n bytes calldata message,\\n uint256 maxCount\\n ) external payable {\\n // call Across spoke pool to bridge assets\\n spokePool.deposit{ value: msg.value }(\\n receiver,\\n wrappedNative,\\n msg.value,\\n destinationChainId,\\n relayerFeePct,\\n quoteTimestamp,\\n message,\\n maxCount\\n );\\n\\n emit LiFiAcrossTransfer(bytes8(transactionId));\\n }\\n\\n /// @notice Bridges ERC20 tokens via Across (packed implementation)\\n /// No params, all data will be extracted from manually encoded callData\\n function startBridgeTokensViaAcrossERC20Packed() external payable {\\n address sendingAssetId = address(bytes20(msg.data[32:52]));\\n uint256 minAmount = uint256(uint128(bytes16(msg.data[52:68])));\\n\\n // Deposit assets\\n ERC20(sendingAssetId).safeTransferFrom(\\n msg.sender,\\n address(this),\\n minAmount\\n );\\n\\n // calculate end of calldata (and start of delimiter + referrer address)\\n uint256 calldataEndsAt = msg.data.length - REFERRER_OFFSET;\\n\\n // call Across spoke pool to bridge assets\\n spokePool.deposit(\\n address(bytes20(msg.data[12:32])), // receiver\\n address(bytes20(msg.data[32:52])), // sendingAssetID\\n minAmount,\\n uint64(uint32(bytes4(msg.data[68:72]))), // destinationChainId\\n int64(uint64(bytes8(msg.data[72:80]))), // int64 relayerFeePct\\n uint32(bytes4(msg.data[80:84])), // uint32 quoteTimestamp\\n msg.data[116:calldataEndsAt], // bytes message (due to variable length positioned at the end of the calldata)\\n uint256(bytes32(msg.data[84:116])) // uint256 maxCount\\n );\\n\\n emit LiFiAcrossTransfer(bytes8(msg.data[4:12]));\\n }\\n\\n /// @notice Bridges ERC20 tokens via Across (minimal implementation)\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param sendingAssetId The address of the asset/token to be bridged\\n /// @param minAmount The amount to be bridged\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param relayerFeePct The relayer fee in token percentage with 18 decimals\\n /// @param quoteTimestamp The timestamp associated with the suggested fee\\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens\\n /// @param maxCount Used to protect the depositor from frontrunning to guarantee their quote remains valid\\n function startBridgeTokensViaAcrossERC20Min(\\n bytes32 transactionId,\\n address sendingAssetId,\\n uint256 minAmount,\\n address receiver,\\n uint64 destinationChainId,\\n int64 relayerFeePct,\\n uint32 quoteTimestamp,\\n bytes calldata message,\\n uint256 maxCount\\n ) external payable {\\n // Deposit assets\\n ERC20(sendingAssetId).safeTransferFrom(\\n msg.sender,\\n address(this),\\n minAmount\\n );\\n\\n // call Across spoke pool to bridge assets\\n spokePool.deposit(\\n receiver,\\n sendingAssetId,\\n minAmount,\\n destinationChainId,\\n relayerFeePct,\\n quoteTimestamp,\\n message,\\n maxCount\\n );\\n\\n emit LiFiAcrossTransfer(bytes8(transactionId));\\n }\\n\\n /// @notice Encodes calldata that can be used to call the native 'packed' function\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param relayerFeePct The relayer fee in token percentage with 18 decimals\\n /// @param quoteTimestamp The timestamp associated with the suggested fee\\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens\\n /// @param maxCount Used to protect the depositor from frontrunning to guarantee their quote remains valid\\n function encode_startBridgeTokensViaAcrossNativePacked(\\n bytes32 transactionId,\\n address receiver,\\n uint64 destinationChainId,\\n int64 relayerFeePct,\\n uint32 quoteTimestamp,\\n uint256 maxCount,\\n bytes calldata message\\n ) external pure returns (bytes memory) {\\n // there are already existing networks with chainIds outside uint32 range but since we not support either of them yet,\\n // we feel comfortable using this approach to save further gas\\n require(\\n destinationChainId <= type(uint32).max,\\n \\\"destinationChainId value passed too big to fit in uint32\\\"\\n );\\n\\n return\\n bytes.concat(\\n AcrossFacetPacked\\n .startBridgeTokensViaAcrossNativePacked\\n .selector,\\n bytes8(transactionId),\\n bytes20(receiver),\\n bytes4(uint32(destinationChainId)),\\n bytes8(uint64(relayerFeePct)),\\n bytes4(quoteTimestamp),\\n bytes32(maxCount),\\n message\\n );\\n }\\n\\n /// @notice Encodes calldata that can be used to call the ERC20 'packed' function\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param sendingAssetId The address of the asset/token to be bridged\\n /// @param minAmount The amount to be bridged\\n /// @param destinationChainId Receiving chain\\n /// @param relayerFeePct The relayer fee in token percentage with 18 decimals\\n /// @param quoteTimestamp The timestamp associated with the suggested fee\\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens\\n /// @param maxCount Used to protect the depositor from frontrunning to guarantee their quote remains valid\\n function encode_startBridgeTokensViaAcrossERC20Packed(\\n bytes32 transactionId,\\n address receiver,\\n address sendingAssetId,\\n uint256 minAmount,\\n uint256 destinationChainId,\\n int64 relayerFeePct,\\n uint32 quoteTimestamp,\\n bytes calldata message,\\n uint256 maxCount\\n ) external pure returns (bytes memory) {\\n // there are already existing networks with chainIds outside uint32 range but since we not support either of them yet,\\n // we feel comfortable using this approach to save further gas\\n require(\\n destinationChainId <= type(uint32).max,\\n \\\"destinationChainId value passed too big to fit in uint32\\\"\\n );\\n\\n require(\\n minAmount <= type(uint128).max,\\n \\\"minAmount value passed too big to fit in uint128\\\"\\n );\\n\\n return\\n bytes.concat(\\n AcrossFacetPacked\\n .startBridgeTokensViaAcrossERC20Packed\\n .selector,\\n bytes8(transactionId),\\n bytes20(receiver),\\n bytes20(sendingAssetId),\\n bytes16(uint128(minAmount)),\\n bytes4(uint32(destinationChainId)),\\n bytes8(uint64(relayerFeePct)),\\n bytes4(uint32(quoteTimestamp)),\\n bytes32(maxCount),\\n message\\n );\\n }\\n\\n /// @notice Decodes calldata that is meant to be used for calling the native 'packed' function\\n /// @param data the calldata to be decoded\\n function decode_startBridgeTokensViaAcrossNativePacked(\\n bytes calldata data\\n )\\n external\\n pure\\n returns (\\n BridgeData memory bridgeData,\\n AcrossFacet.AcrossData memory acrossData\\n )\\n {\\n require(\\n data.length >= 108,\\n \\\"invalid calldata (must have length > 108)\\\"\\n );\\n\\n // calculate end of calldata (and start of delimiter + referrer address)\\n uint256 calldataEndsAt = data.length - REFERRER_OFFSET;\\n\\n // extract bridgeData\\n bridgeData.transactionId = bytes32(bytes8(data[4:12]));\\n bridgeData.receiver = address(bytes20(data[12:32]));\\n bridgeData.destinationChainId = uint64(uint32(bytes4(data[32:36])));\\n\\n // extract acrossData\\n acrossData.relayerFeePct = int64(uint64(bytes8(data[36:44])));\\n acrossData.quoteTimestamp = uint32(bytes4(data[44:48]));\\n acrossData.maxCount = uint256(bytes32(data[48:80]));\\n acrossData.message = data[80:calldataEndsAt];\\n\\n return (bridgeData, acrossData);\\n }\\n\\n /// @notice Decodes calldata that is meant to be used for calling the ERC20 'packed' function\\n /// @param data the calldata to be decoded\\n function decode_startBridgeTokensViaAcrossERC20Packed(\\n bytes calldata data\\n )\\n external\\n pure\\n returns (\\n BridgeData memory bridgeData,\\n AcrossFacet.AcrossData memory acrossData\\n )\\n {\\n require(\\n data.length >= 144,\\n \\\"invalid calldata (must have length > 144)\\\"\\n );\\n\\n // calculate end of calldata (and start of delimiter + referrer address)\\n uint256 calldataEndsAt = data.length - REFERRER_OFFSET;\\n\\n bridgeData.transactionId = bytes32(bytes8(data[4:12]));\\n bridgeData.receiver = address(bytes20(data[12:32]));\\n bridgeData.sendingAssetId = address(bytes20(data[32:52]));\\n bridgeData.minAmount = uint256(uint128(bytes16(data[52:68])));\\n bridgeData.destinationChainId = uint64(uint32(bytes4(data[68:72])));\\n\\n // extract acrossData\\n acrossData.relayerFeePct = int64(uint64(bytes8(data[72:80])));\\n acrossData.quoteTimestamp = uint32(bytes4(data[80:84]));\\n acrossData.maxCount = uint256(bytes32(data[84:116]));\\n acrossData.message = data[116:calldataEndsAt];\\n\\n return (bridgeData, acrossData);\\n }\\n\\n /// @notice Execute calldata and withdraw asset\\n /// @param _callTo The address to execute the calldata on\\n /// @param _callData The data to execute\\n /// @param _assetAddress Asset to be withdrawn\\n /// @param _to address to withdraw to\\n /// @param _amount amount of asset to withdraw\\n function executeCallAndWithdraw(\\n address _callTo,\\n bytes calldata _callData,\\n address _assetAddress,\\n address _to,\\n uint256 _amount\\n ) external onlyOwner {\\n // execute calldata\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = _callTo.call(_callData);\\n\\n // check success of call\\n if (success) {\\n // call successful - withdraw the asset\\n LibAsset.transferAsset(_assetAddress, payable(_to), _amount);\\n emit CallExecutedAndFundsWithdrawn();\\n } else {\\n // call unsuccessful - revert\\n revert WithdrawFailed();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IAcrossSpokePool.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IAcrossSpokePool {\\n function deposit(\\n address recipient, // Recipient address\\n address originToken, // Address of the token\\n uint256 amount, // Token amount\\n uint256 destinationChainId, // ⛓ id\\n int64 relayerFeePct, // see #Fees Calculation\\n uint32 quoteTimestamp, // Timestamp for the quote creation\\n bytes memory message, // Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\\n uint256 maxCount // Used to protect the depositor from frontrunning to guarantee their quote remains valid.\\n ) external payable;\\n}\\n\"\r\n },\r\n \"src/Helpers/TransferrableOwnership.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IERC173 } from \\\"../Interfaces/IERC173.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\n\\ncontract TransferrableOwnership is IERC173 {\\n address public owner;\\n address public pendingOwner;\\n\\n /// Errors ///\\n error UnAuthorized();\\n error NoNullOwner();\\n error NewOwnerMustNotBeSelf();\\n error NoPendingOwnershipTransfer();\\n error NotPendingOwner();\\n\\n /// Events ///\\n event OwnershipTransferRequested(\\n address indexed _from,\\n address indexed _to\\n );\\n\\n constructor(address initialOwner) {\\n owner = initialOwner;\\n }\\n\\n modifier onlyOwner() {\\n if (msg.sender != owner) revert UnAuthorized();\\n _;\\n }\\n\\n /// @notice Initiates transfer of ownership to a new address\\n /// @param _newOwner the address to transfer ownership to\\n function transferOwnership(address _newOwner) external onlyOwner {\\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\\n pendingOwner = _newOwner;\\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\\n }\\n\\n /// @notice Cancel transfer of ownership\\n function cancelOwnershipTransfer() external onlyOwner {\\n if (pendingOwner == LibAsset.NULL_ADDRESS)\\n revert NoPendingOwnershipTransfer();\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n\\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\\n function confirmOwnershipTransfer() external {\\n address _pendingOwner = pendingOwner;\\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\\n emit OwnershipTransferred(owner, _pendingOwner);\\n owner = _pendingOwner;\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n}\\n\"\r\n },\r\n \"src/Facets/AcrossFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IAcrossSpokePool } from \\\"../Interfaces/IAcrossSpokePool.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2 } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title Across Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Across Protocol\\n/// @custom:version 2.0.0\\ncontract AcrossFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n /// @notice The contract address of the spoke pool on the source chain.\\n IAcrossSpokePool private immutable spokePool;\\n\\n /// @notice The WETH address on the current chain.\\n address private immutable wrappedNative;\\n\\n /// Types ///\\n\\n /// @param relayerFeePct The relayer fee in token percentage with 18 decimals.\\n /// @param quoteTimestamp The timestamp associated with the suggested fee.\\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\\n /// @param maxCount Used to protect the depositor from frontrunning to guarantee their quote remains valid.\\n struct AcrossData {\\n int64 relayerFeePct;\\n uint32 quoteTimestamp;\\n bytes message;\\n uint256 maxCount;\\n }\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _spokePool The contract address of the spoke pool on the source chain.\\n /// @param _wrappedNative The address of the wrapped native token on the source chain.\\n constructor(IAcrossSpokePool _spokePool, address _wrappedNative) {\\n spokePool = _spokePool;\\n wrappedNative = _wrappedNative;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Across\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _acrossData data specific to Across\\n function startBridgeTokensViaAcross(\\n ILiFi.BridgeData memory _bridgeData,\\n AcrossData calldata _acrossData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n validateBridgeData(_bridgeData)\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData, _acrossData);\\n }\\n\\n /// @notice Performs a swap before bridging via Across\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _acrossData data specific to Across\\n function swapAndStartBridgeTokensViaAcross(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n AcrossData calldata _acrossData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n _startBridge(_bridgeData, _acrossData);\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Across\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _acrossData data specific to Across\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n AcrossData calldata _acrossData\\n ) internal {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n spokePool.deposit{ value: _bridgeData.minAmount }(\\n _bridgeData.receiver,\\n wrappedNative,\\n _bridgeData.minAmount,\\n _bridgeData.destinationChainId,\\n _acrossData.relayerFeePct,\\n _acrossData.quoteTimestamp,\\n _acrossData.message,\\n _acrossData.maxCount\\n );\\n } else {\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(spokePool),\\n _bridgeData.minAmount\\n );\\n spokePool.deposit(\\n _bridgeData.receiver,\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n _bridgeData.destinationChainId,\\n _acrossData.relayerFeePct,\\n _acrossData.quoteTimestamp,\\n _acrossData.message,\\n _acrossData.maxCount\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"lib/solmate/src/utils/SafeTransferLib.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\nimport {ERC20} from \\\"../tokens/ERC20.sol\\\";\\n\\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\\nlibrary SafeTransferLib {\\n /*//////////////////////////////////////////////////////////////\\n ETH OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferETH(address to, uint256 amount) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Transfer the ETH and store if it succeeded or not.\\n success := call(gas(), to, amount, 0, 0, 0, 0)\\n }\\n\\n require(success, \\\"ETH_TRANSFER_FAILED\\\");\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferFrom(\\n ERC20 token,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), from) // Append the \\\"from\\\" argument.\\n mstore(add(freeMemoryPointer, 36), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 68), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FROM_FAILED\\\");\\n }\\n\\n function safeTransfer(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FAILED\\\");\\n }\\n\\n function safeApprove(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"APPROVE_FAILED\\\");\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"lib/forge-std/src/console2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.22 <0.9.0;\\n\\n/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should\\n/// use `int256` and `uint256`. This modified version fixes that. This version is recommended\\n/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in\\n/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.\\n/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178\\nlibrary console2 {\\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n function _castLogPayloadViewToPure(\\n function(bytes memory) internal view fnIn\\n ) internal pure returns (function(bytes memory) internal pure fnOut) {\\n assembly {\\n fnOut := fnIn\\n }\\n }\\n\\n function _sendLogPayload(bytes memory payload) internal pure {\\n _castLogPayloadViewToPure(_sendLogPayloadView)(payload);\\n }\\n\\n function _sendLogPayloadView(bytes memory payload) private view {\\n uint256 payloadLength = payload.length;\\n address consoleAddress = CONSOLE_ADDRESS;\\n /// @solidity memory-safe-assembly\\n assembly {\\n let payloadStart := add(payload, 32)\\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n }\\n }\\n\\n function log() internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n }\\n\\n function logInt(int256 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(int256)\\\", p0));\\n }\\n\\n function logUint(uint256 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256)\\\", p0));\\n }\\n\\n function logString(string memory p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n }\\n\\n function logBool(bool p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n }\\n\\n function logAddress(address p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n }\\n\\n function logBytes(bytes memory p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n }\\n\\n function logBytes1(bytes1 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n }\\n\\n function logBytes2(bytes2 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n }\\n\\n function logBytes3(bytes3 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n }\\n\\n function logBytes4(bytes4 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n }\\n\\n function logBytes5(bytes5 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n }\\n\\n function logBytes6(bytes6 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n }\\n\\n function logBytes7(bytes7 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n }\\n\\n function logBytes8(bytes8 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n }\\n\\n function logBytes9(bytes9 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n }\\n\\n function logBytes10(bytes10 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n }\\n\\n function logBytes11(bytes11 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n }\\n\\n function logBytes12(bytes12 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n }\\n\\n function logBytes13(bytes13 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n }\\n\\n function logBytes14(bytes14 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n }\\n\\n function logBytes15(bytes15 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n }\\n\\n function logBytes16(bytes16 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n }\\n\\n function logBytes17(bytes17 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n }\\n\\n function logBytes18(bytes18 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n }\\n\\n function logBytes19(bytes19 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n }\\n\\n function logBytes20(bytes20 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n }\\n\\n function logBytes21(bytes21 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n }\\n\\n function logBytes22(bytes22 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n }\\n\\n function logBytes23(bytes23 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n }\\n\\n function logBytes24(bytes24 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n }\\n\\n function logBytes25(bytes25 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n }\\n\\n function logBytes26(bytes26 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n }\\n\\n function logBytes27(bytes27 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n }\\n\\n function logBytes28(bytes28 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n }\\n\\n function logBytes29(bytes29 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n }\\n\\n function logBytes30(bytes30 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n }\\n\\n function logBytes31(bytes31 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n }\\n\\n function logBytes32(bytes32 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n }\\n\\n function log(uint256 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256)\\\", p0));\\n }\\n\\n function log(int256 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(int256)\\\", p0));\\n }\\n\\n function log(string memory p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n }\\n\\n function log(bool p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n }\\n\\n function log(address p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n }\\n\\n function log(uint256 p0, uint256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256)\\\", p0, p1));\\n }\\n\\n function log(uint256 p0, string memory p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string)\\\", p0, p1));\\n }\\n\\n function log(uint256 p0, bool p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool)\\\", p0, p1));\\n }\\n\\n function log(uint256 p0, address p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, uint256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, int256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,int256)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, string memory p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, bool p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, address p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n }\\n\\n function log(bool p0, uint256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256)\\\", p0, p1));\\n }\\n\\n function log(bool p0, string memory p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n }\\n\\n function log(bool p0, bool p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n }\\n\\n function log(bool p0, address p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n }\\n\\n function log(address p0, uint256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256)\\\", p0, p1));\\n }\\n\\n function log(address p0, string memory p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n }\\n\\n function log(address p0, bool p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n }\\n\\n function log(address p0, address p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, bool p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, address p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, address p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, string memory p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, bool p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, bool p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, address p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, address p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, address p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, uint256 p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, string memory p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, string memory p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, bool p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, bool p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, bool p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, address p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, address p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, address p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, address p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, uint256 p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, uint256 p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, string memory p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, string memory p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, string memory p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, bool p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, bool p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, bool p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, bool p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, address p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, address p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, address p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, address p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n}\"\r\n },\r\n \"src/Interfaces/IERC173.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\n/// @title ERC-173 Contract Ownership Standard\\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\\n/* is ERC165 */\\ninterface IERC173 {\\n /// @dev This emits when ownership of a contract changes.\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n /// @notice Get the address of the owner\\n /// @return owner_ The address of the owner.\\n function owner() external view returns (address owner_);\\n\\n /// @notice Set the address of the new owner of the contract\\n /// @dev Set _newOwner to address(0) to renounce any ownership.\\n /// @param _newOwner The address of the new owner of the contract\\n function transferOwnership(address _newOwner) external;\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"lib/solmate/src/tokens/ERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\\nabstract contract ERC20 {\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /*//////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string public name;\\n\\n string public symbol;\\n\\n uint8 public immutable decimals;\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 public totalSupply;\\n\\n mapping(address => uint256) public balanceOf;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 internal immutable INITIAL_CHAIN_ID;\\n\\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\\n\\n mapping(address => uint256) public nonces;\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n constructor(\\n string memory _name,\\n string memory _symbol,\\n uint8 _decimals\\n ) {\\n name = _name;\\n symbol = _symbol;\\n decimals = _decimals;\\n\\n INITIAL_CHAIN_ID = block.chainid;\\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function approve(address spender, uint256 amount) public virtual returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n\\n return true;\\n }\\n\\n function transfer(address to, uint256 amount) public virtual returns (bool) {\\n balanceOf[msg.sender] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(msg.sender, to, amount);\\n\\n return true;\\n }\\n\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual returns (bool) {\\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\\n\\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\\n\\n balanceOf[from] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n return true;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 LOGIC\\n //////////////////////////////////////////////////////////////*/\\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 ) public virtual {\\n require(deadline >= block.timestamp, \\\"PERMIT_DEADLINE_EXPIRED\\\");\\n\\n // Unchecked because the only math done is incrementing\\n // the owner's nonce which cannot realistically overflow.\\n unchecked {\\n address recoveredAddress = ecrecover(\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR(),\\n keccak256(\\n abi.encode(\\n keccak256(\\n \\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\"\\n ),\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n require(recoveredAddress != address(0) && recoveredAddress == owner, \\\"INVALID_SIGNER\\\");\\n\\n allowance[recoveredAddress][spender] = value;\\n }\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\\n }\\n\\n function computeDomainSeparator() internal view virtual returns (bytes32) {\\n return\\n keccak256(\\n abi.encode(\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"),\\n keccak256(bytes(name)),\\n keccak256(\\\"1\\\"),\\n block.chainid,\\n address(this)\\n )\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _mint(address to, uint256 amount) internal virtual {\\n totalSupply += amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(address(0), to, amount);\\n }\\n\\n function _burn(address from, uint256 amount) internal virtual {\\n balanceOf[from] -= amount;\\n\\n // Cannot underflow because a user's balance\\n // will never be larger than the total supply.\\n unchecked {\\n totalSupply -= amount;\\n }\\n\\n emit Transfer(from, address(0), amount);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IAcrossSpokePool\",\"name\":\"_spokePool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_wrappedNative\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NewOwnerMustNotBeSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoNullOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoPendingOwnershipTransfer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotPendingOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnAuthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WithdrawFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CallExecutedAndFundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes8\",\"name\":\"_transactionId\",\"type\":\"bytes8\"}],\"name\":\"LiFiAcrossTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"ACROSS_REFERRER_DELIMITER\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelOwnershipTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"confirmOwnershipTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"decode_startBridgeTokensViaAcrossERC20Packed\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"relayerFeePct\",\"type\":\"int64\"},{\"internalType\":\"uint32\",\"name\":\"quoteTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"internalType\":\"struct AcrossFacet.AcrossData\",\"name\":\"acrossData\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"decode_startBridgeTokensViaAcrossNativePacked\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"relayerFeePct\",\"type\":\"int64\"},{\"internalType\":\"uint32\",\"name\":\"quoteTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"internalType\":\"struct AcrossFacet.AcrossData\",\"name\":\"acrossData\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"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\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"encode_startBridgeTokensViaAcrossERC20Packed\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destinationChainId\",\"type\":\"uint64\"},{\"internalType\":\"int64\",\"name\":\"relayerFeePct\",\"type\":\"int64\"},{\"internalType\":\"uint32\",\"name\":\"quoteTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"encode_startBridgeTokensViaAcrossNativePacked\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_callTo\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_callData\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"_assetAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"executeCallAndWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokensToApprove\",\"type\":\"address[]\"}],\"name\":\"setApprovalForBridge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destinationChainId\",\"type\":\"uint64\"},{\"internalType\":\"int64\",\"name\":\"relayerFeePct\",\"type\":\"int64\"},{\"internalType\":\"uint32\",\"name\":\"quoteTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"startBridgeTokensViaAcrossERC20Min\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBridgeTokensViaAcrossERC20Packed\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"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\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"startBridgeTokensViaAcrossNativeMin\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBridgeTokensViaAcrossNativePacked\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ContractName: "AcrossFacetPacked", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000005c7bcd6e7de5423a257d81b442095a1a6ced35c5000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000011f1022ca6adef6400e5677528a80d49a069c00c", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/AcrossFacetPacked.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IAcrossSpokePool } from \"../Interfaces/IAcrossSpokePool.sol\";\nimport { TransferrableOwnership } from \"../Helpers/TransferrableOwnership.sol\";\nimport { AcrossFacet } from \"./AcrossFacet.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { ERC20, SafeTransferLib } from \"solmate/utils/SafeTransferLib.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { console2 } from \"forge-std/console2.sol\";\n\n/// @title AcrossFacetPacked\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Across in a gas-optimized way\n/// @custom:version 1.0.0\ncontract AcrossFacetPacked is ILiFi, TransferrableOwnership {\n using SafeTransferLib for ERC20;\n\n bytes public constant ACROSS_REFERRER_DELIMITER = hex\"d00dfeeddeadbeef\";\n uint8 private constant ACROSS_REFERRER_ADDRESS_LENGTH = 20;\n uint256 private constant REFERRER_OFFSET = 28;\n\n /// Storage ///\n\n /// @notice The contract address of the cbridge on the source chain.\n IAcrossSpokePool private immutable spokePool;\n\n /// @notice The WETH address on the current chain.\n address private immutable wrappedNative;\n\n /// Events ///\n\n event LiFiAcrossTransfer(bytes8 _transactionId);\n event CallExecutedAndFundsWithdrawn();\n\n /// Errors ///\n\n error WithdrawFailed();\n\n /// Constructor ///\n\n /// @notice Initialize the contract\n /// @param _spokePool The contract address of the spoke pool on the source chain\n /// @param _wrappedNative The address of the wrapped native token on the source chain\n /// @param _owner The address of the contract owner\n constructor(\n IAcrossSpokePool _spokePool,\n address _wrappedNative,\n address _owner\n ) TransferrableOwnership(_owner) {\n spokePool = _spokePool;\n wrappedNative = _wrappedNative;\n }\n\n /// External Methods ///\n\n /// @dev Only meant to be called outside of the context of the diamond\n /// @notice Sets approval for the Across spoke pool Router to spend the specified token\n /// @param tokensToApprove The tokens to approve to the Across spoke pool\n function setApprovalForBridge(\n address[] calldata tokensToApprove\n ) external onlyOwner {\n for (uint256 i; i < tokensToApprove.length; i++) {\n // Give Across spoke pool approval to pull tokens from this facet\n LibAsset.maxApproveERC20(\n IERC20(tokensToApprove[i]),\n address(spokePool),\n type(uint256).max\n );\n }\n }\n\n /// @notice Bridges native tokens via Across (packed implementation)\n /// No params, all data will be extracted from manually encoded callData\n function startBridgeTokensViaAcrossNativePacked() external payable {\n // calculate end of calldata (and start of delimiter + referrer address)\n uint256 calldataEndsAt = msg.data.length - REFERRER_OFFSET;\n\n // call Across spoke pool to bridge assets\n spokePool.deposit{ value: msg.value }(\n address(bytes20(msg.data[12:32])), // receiver\n wrappedNative, // wrappedNative address\n msg.value, // minAmount\n uint64(uint32(bytes4(msg.data[32:36]))), // destinationChainId\n int64(uint64(bytes8(msg.data[36:44]))), // int64 relayerFeePct\n uint32(bytes4(msg.data[44:48])), // uint32 quoteTimestamp\n msg.data[80:calldataEndsAt], // bytes message (due to variable length positioned at the end of the calldata)\n uint256(bytes32(msg.data[48:80])) // uint256 maxCount\n );\n\n emit LiFiAcrossTransfer(bytes8(msg.data[4:12]));\n }\n\n /// @notice Bridges native tokens via Across (minimal implementation)\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param relayerFeePct The relayer fee in token percentage with 18 decimals\n /// @param quoteTimestamp The timestamp associated with the suggested fee\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens\n /// @param maxCount Used to protect the depositor from frontrunning to guarantee their quote remains valid\n function startBridgeTokensViaAcrossNativeMin(\n bytes32 transactionId,\n address receiver,\n uint256 destinationChainId,\n int64 relayerFeePct,\n uint32 quoteTimestamp,\n bytes calldata message,\n uint256 maxCount\n ) external payable {\n // call Across spoke pool to bridge assets\n spokePool.deposit{ value: msg.value }(\n receiver,\n wrappedNative,\n msg.value,\n destinationChainId,\n relayerFeePct,\n quoteTimestamp,\n message,\n maxCount\n );\n\n emit LiFiAcrossTransfer(bytes8(transactionId));\n }\n\n /// @notice Bridges ERC20 tokens via Across (packed implementation)\n /// No params, all data will be extracted from manually encoded callData\n function startBridgeTokensViaAcrossERC20Packed() external payable {\n address sendingAssetId = address(bytes20(msg.data[32:52]));\n uint256 minAmount = uint256(uint128(bytes16(msg.data[52:68])));\n\n // Deposit assets\n ERC20(sendingAssetId).safeTransferFrom(\n msg.sender,\n address(this),\n minAmount\n );\n\n // calculate end of calldata (and start of delimiter + referrer address)\n uint256 calldataEndsAt = msg.data.length - REFERRER_OFFSET;\n\n // call Across spoke pool to bridge assets\n spokePool.deposit(\n address(bytes20(msg.data[12:32])), // receiver\n address(bytes20(msg.data[32:52])), // sendingAssetID\n minAmount,\n uint64(uint32(bytes4(msg.data[68:72]))), // destinationChainId\n int64(uint64(bytes8(msg.data[72:80]))), // int64 relayerFeePct\n uint32(bytes4(msg.data[80:84])), // uint32 quoteTimestamp\n msg.data[116:calldataEndsAt], // bytes message (due to variable length positioned at the end of the calldata)\n uint256(bytes32(msg.data[84:116])) // uint256 maxCount\n );\n\n emit LiFiAcrossTransfer(bytes8(msg.data[4:12]));\n }\n\n /// @notice Bridges ERC20 tokens via Across (minimal implementation)\n /// @param transactionId Custom transaction ID for tracking\n /// @param sendingAssetId The address of the asset/token to be bridged\n /// @param minAmount The amount to be bridged\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param relayerFeePct The relayer fee in token percentage with 18 decimals\n /// @param quoteTimestamp The timestamp associated with the suggested fee\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens\n /// @param maxCount Used to protect the depositor from frontrunning to guarantee their quote remains valid\n function startBridgeTokensViaAcrossERC20Min(\n bytes32 transactionId,\n address sendingAssetId,\n uint256 minAmount,\n address receiver,\n uint64 destinationChainId,\n int64 relayerFeePct,\n uint32 quoteTimestamp,\n bytes calldata message,\n uint256 maxCount\n ) external payable {\n // Deposit assets\n ERC20(sendingAssetId).safeTransferFrom(\n msg.sender,\n address(this),\n minAmount\n );\n\n // call Across spoke pool to bridge assets\n spokePool.deposit(\n receiver,\n sendingAssetId,\n minAmount,\n destinationChainId,\n relayerFeePct,\n quoteTimestamp,\n message,\n maxCount\n );\n\n emit LiFiAcrossTransfer(bytes8(transactionId));\n }\n\n /// @notice Encodes calldata that can be used to call the native 'packed' function\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param relayerFeePct The relayer fee in token percentage with 18 decimals\n /// @param quoteTimestamp The timestamp associated with the suggested fee\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens\n /// @param maxCount Used to protect the depositor from frontrunning to guarantee their quote remains valid\n function encode_startBridgeTokensViaAcrossNativePacked(\n bytes32 transactionId,\n address receiver,\n uint64 destinationChainId,\n int64 relayerFeePct,\n uint32 quoteTimestamp,\n uint256 maxCount,\n bytes calldata message\n ) external pure returns (bytes memory) {\n // there are already existing networks with chainIds outside uint32 range but since we not support either of them yet,\n // we feel comfortable using this approach to save further gas\n require(\n destinationChainId <= type(uint32).max,\n \"destinationChainId value passed too big to fit in uint32\"\n );\n\n return\n bytes.concat(\n AcrossFacetPacked\n .startBridgeTokensViaAcrossNativePacked\n .selector,\n bytes8(transactionId),\n bytes20(receiver),\n bytes4(uint32(destinationChainId)),\n bytes8(uint64(relayerFeePct)),\n bytes4(quoteTimestamp),\n bytes32(maxCount),\n message\n );\n }\n\n /// @notice Encodes calldata that can be used to call the ERC20 'packed' function\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param sendingAssetId The address of the asset/token to be bridged\n /// @param minAmount The amount to be bridged\n /// @param destinationChainId Receiving chain\n /// @param relayerFeePct The relayer fee in token percentage with 18 decimals\n /// @param quoteTimestamp The timestamp associated with the suggested fee\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens\n /// @param maxCount Used to protect the depositor from frontrunning to guarantee their quote remains valid\n function encode_startBridgeTokensViaAcrossERC20Packed(\n bytes32 transactionId,\n address receiver,\n address sendingAssetId,\n uint256 minAmount,\n uint256 destinationChainId,\n int64 relayerFeePct,\n uint32 quoteTimestamp,\n bytes calldata message,\n uint256 maxCount\n ) external pure returns (bytes memory) {\n // there are already existing networks with chainIds outside uint32 range but since we not support either of them yet,\n // we feel comfortable using this approach to save further gas\n require(\n destinationChainId <= type(uint32).max,\n \"destinationChainId value passed too big to fit in uint32\"\n );\n\n require(\n minAmount <= type(uint128).max,\n \"minAmount value passed too big to fit in uint128\"\n );\n\n return\n bytes.concat(\n AcrossFacetPacked\n .startBridgeTokensViaAcrossERC20Packed\n .selector,\n bytes8(transactionId),\n bytes20(receiver),\n bytes20(sendingAssetId),\n bytes16(uint128(minAmount)),\n bytes4(uint32(destinationChainId)),\n bytes8(uint64(relayerFeePct)),\n bytes4(uint32(quoteTimestamp)),\n bytes32(maxCount),\n message\n );\n }\n\n /// @notice Decodes calldata that is meant to be used for calling the native 'packed' function\n /// @param data the calldata to be decoded\n function decode_startBridgeTokensViaAcrossNativePacked(\n bytes calldata data\n )\n external\n pure\n returns (\n BridgeData memory bridgeData,\n AcrossFacet.AcrossData memory acrossData\n )\n {\n require(\n data.length >= 108,\n \"invalid calldata (must have length > 108)\"\n );\n\n // calculate end of calldata (and start of delimiter + referrer address)\n uint256 calldataEndsAt = data.length - REFERRER_OFFSET;\n\n // extract bridgeData\n bridgeData.transactionId = bytes32(bytes8(data[4:12]));\n bridgeData.receiver = address(bytes20(data[12:32]));\n bridgeData.destinationChainId = uint64(uint32(bytes4(data[32:36])));\n\n // extract acrossData\n acrossData.relayerFeePct = int64(uint64(bytes8(data[36:44])));\n acrossData.quoteTimestamp = uint32(bytes4(data[44:48]));\n acrossData.maxCount = uint256(bytes32(data[48:80]));\n acrossData.message = data[80:calldataEndsAt];\n\n return (bridgeData, acrossData);\n }\n\n /// @notice Decodes calldata that is meant to be used for calling the ERC20 'packed' function\n /// @param data the calldata to be decoded\n function decode_startBridgeTokensViaAcrossERC20Packed(\n bytes calldata data\n )\n external\n pure\n returns (\n BridgeData memory bridgeData,\n AcrossFacet.AcrossData memory acrossData\n )\n {\n require(\n data.length >= 144,\n \"invalid calldata (must have length > 144)\"\n );\n\n // calculate end of calldata (and start of delimiter + referrer address)\n uint256 calldataEndsAt = data.length - REFERRER_OFFSET;\n\n bridgeData.transactionId = bytes32(bytes8(data[4:12]));\n bridgeData.receiver = address(bytes20(data[12:32]));\n bridgeData.sendingAssetId = address(bytes20(data[32:52]));\n bridgeData.minAmount = uint256(uint128(bytes16(data[52:68])));\n bridgeData.destinationChainId = uint64(uint32(bytes4(data[68:72])));\n\n // extract acrossData\n acrossData.relayerFeePct = int64(uint64(bytes8(data[72:80])));\n acrossData.quoteTimestamp = uint32(bytes4(data[80:84]));\n acrossData.maxCount = uint256(bytes32(data[84:116]));\n acrossData.message = data[116:calldataEndsAt];\n\n return (bridgeData, acrossData);\n }\n\n /// @notice Execute calldata and withdraw asset\n /// @param _callTo The address to execute the calldata on\n /// @param _callData The data to execute\n /// @param _assetAddress Asset to be withdrawn\n /// @param _to address to withdraw to\n /// @param _amount amount of asset to withdraw\n function executeCallAndWithdraw(\n address _callTo,\n bytes calldata _callData,\n address _assetAddress,\n address _to,\n uint256 _amount\n ) external onlyOwner {\n // execute calldata\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = _callTo.call(_callData);\n\n // check success of call\n if (success) {\n // call successful - withdraw the asset\n LibAsset.transferAsset(_assetAddress, payable(_to), _amount);\n emit CallExecutedAndFundsWithdrawn();\n } else {\n // call unsuccessful - revert\n revert WithdrawFailed();\n }\n }\n}\n" + }, + "src/Interfaces/IAcrossSpokePool.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IAcrossSpokePool {\n function deposit(\n address recipient, // Recipient address\n address originToken, // Address of the token\n uint256 amount, // Token amount\n uint256 destinationChainId, // ⛓ id\n int64 relayerFeePct, // see #Fees Calculation\n uint32 quoteTimestamp, // Timestamp for the quote creation\n bytes memory message, // Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\n uint256 maxCount // Used to protect the depositor from frontrunning to guarantee their quote remains valid.\n ) external payable;\n}\n" + }, + "src/Helpers/TransferrableOwnership.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IERC173 } from \"../Interfaces/IERC173.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\n\ncontract TransferrableOwnership is IERC173 {\n address public owner;\n address public pendingOwner;\n\n /// Errors ///\n error UnAuthorized();\n error NoNullOwner();\n error NewOwnerMustNotBeSelf();\n error NoPendingOwnershipTransfer();\n error NotPendingOwner();\n\n /// Events ///\n event OwnershipTransferRequested(\n address indexed _from,\n address indexed _to\n );\n\n constructor(address initialOwner) {\n owner = initialOwner;\n }\n\n modifier onlyOwner() {\n if (msg.sender != owner) revert UnAuthorized();\n _;\n }\n\n /// @notice Initiates transfer of ownership to a new address\n /// @param _newOwner the address to transfer ownership to\n function transferOwnership(address _newOwner) external onlyOwner {\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\n pendingOwner = _newOwner;\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\n }\n\n /// @notice Cancel transfer of ownership\n function cancelOwnershipTransfer() external onlyOwner {\n if (pendingOwner == LibAsset.NULL_ADDRESS)\n revert NoPendingOwnershipTransfer();\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\n function confirmOwnershipTransfer() external {\n address _pendingOwner = pendingOwner;\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n}\n" + }, + "src/Facets/AcrossFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IAcrossSpokePool } from \"../Interfaces/IAcrossSpokePool.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2 } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title Across Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Across Protocol\n/// @custom:version 2.0.0\ncontract AcrossFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n /// @notice The contract address of the spoke pool on the source chain.\n IAcrossSpokePool private immutable spokePool;\n\n /// @notice The WETH address on the current chain.\n address private immutable wrappedNative;\n\n /// Types ///\n\n /// @param relayerFeePct The relayer fee in token percentage with 18 decimals.\n /// @param quoteTimestamp The timestamp associated with the suggested fee.\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\n /// @param maxCount Used to protect the depositor from frontrunning to guarantee their quote remains valid.\n struct AcrossData {\n int64 relayerFeePct;\n uint32 quoteTimestamp;\n bytes message;\n uint256 maxCount;\n }\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _spokePool The contract address of the spoke pool on the source chain.\n /// @param _wrappedNative The address of the wrapped native token on the source chain.\n constructor(IAcrossSpokePool _spokePool, address _wrappedNative) {\n spokePool = _spokePool;\n wrappedNative = _wrappedNative;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Across\n /// @param _bridgeData the core information needed for bridging\n /// @param _acrossData data specific to Across\n function startBridgeTokensViaAcross(\n ILiFi.BridgeData memory _bridgeData,\n AcrossData calldata _acrossData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n validateBridgeData(_bridgeData)\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData, _acrossData);\n }\n\n /// @notice Performs a swap before bridging via Across\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _acrossData data specific to Across\n function swapAndStartBridgeTokensViaAcross(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n AcrossData calldata _acrossData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n _startBridge(_bridgeData, _acrossData);\n }\n\n /// Internal Methods ///\n\n /// @dev Contains the business logic for the bridge via Across\n /// @param _bridgeData the core information needed for bridging\n /// @param _acrossData data specific to Across\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n AcrossData calldata _acrossData\n ) internal {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n spokePool.deposit{ value: _bridgeData.minAmount }(\n _bridgeData.receiver,\n wrappedNative,\n _bridgeData.minAmount,\n _bridgeData.destinationChainId,\n _acrossData.relayerFeePct,\n _acrossData.quoteTimestamp,\n _acrossData.message,\n _acrossData.maxCount\n );\n } else {\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(spokePool),\n _bridgeData.minAmount\n );\n spokePool.deposit(\n _bridgeData.receiver,\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n _bridgeData.destinationChainId,\n _acrossData.relayerFeePct,\n _acrossData.quoteTimestamp,\n _acrossData.message,\n _acrossData.maxCount\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "lib/solmate/src/utils/SafeTransferLib.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20} from \"../tokens/ERC20.sol\";\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n /*//////////////////////////////////////////////////////////////\n ETH OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferETH(address to, uint256 amount) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Transfer the ETH and store if it succeeded or not.\n success := call(gas(), to, amount, 0, 0, 0, 0)\n }\n\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferFrom(\n ERC20 token,\n address from,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), from) // Append the \"from\" argument.\n mstore(add(freeMemoryPointer, 36), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 68), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FROM_FAILED\");\n }\n\n function safeTransfer(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FAILED\");\n }\n\n function safeApprove(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"APPROVE_FAILED\");\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "lib/forge-std/src/console2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\n/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should\n/// use `int256` and `uint256`. This modified version fixes that. This version is recommended\n/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in\n/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.\n/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178\nlibrary console2 {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _castLogPayloadViewToPure(\n function(bytes memory) internal view fnIn\n ) internal pure returns (function(bytes memory) internal pure fnOut) {\n assembly {\n fnOut := fnIn\n }\n }\n\n function _sendLogPayload(bytes memory payload) internal pure {\n _castLogPayloadViewToPure(_sendLogPayloadView)(payload);\n }\n\n function _sendLogPayloadView(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function logUint(uint256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function logString(string memory p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function log(int256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function log(string memory p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint256 p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256)\", p0, p1));\n }\n\n function log(uint256 p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string)\", p0, p1));\n }\n\n function log(uint256 p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool)\", p0, p1));\n }\n\n function log(uint256 p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address)\", p0, p1));\n }\n\n function log(string memory p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n }\n\n function log(string memory p0, int256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,int256)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" + }, + "src/Interfaces/IERC173.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\n/// @title ERC-173 Contract Ownership Standard\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\n/* is ERC165 */\ninterface IERC173 {\n /// @dev This emits when ownership of a contract changes.\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n /// @notice Get the address of the owner\n /// @return owner_ The address of the owner.\n function owner() external view returns (address owner_);\n\n /// @notice Set the address of the new owner of the contract\n /// @dev Set _newOwner to address(0) to renounce any ownership.\n /// @param _newOwner The address of the new owner of the contract\n function transferOwnership(address _newOwner) external;\n}\n" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "lib/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\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 ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... -DexManagerFacet +0x22b31a1a81d5e594315c866616db793e799556c5 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/DexManagerFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { LibAccess } from \\\"../Libraries/LibAccess.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { CannotAuthoriseSelf } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Dex Manager Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Facet contract for managing approved DEXs to be used in swaps.\\n/// @custom:version 1.0.1\\ncontract DexManagerFacet {\\n /// Events ///\\n\\n event DexAdded(address indexed dexAddress);\\n event DexRemoved(address indexed dexAddress);\\n event FunctionSignatureApprovalChanged(\\n bytes4 indexed functionSignature,\\n bool indexed approved\\n );\\n\\n /// External Methods ///\\n\\n /// @notice Register the address of a DEX contract to be approved for swapping.\\n /// @param _dex The address of the DEX contract to be approved.\\n function addDex(address _dex) external {\\n if (msg.sender != LibDiamond.contractOwner()) {\\n LibAccess.enforceAccessControl();\\n }\\n\\n LibAllowList.addAllowedContract(_dex);\\n\\n emit DexAdded(_dex);\\n }\\n\\n /// @notice Batch register the address of DEX contracts to be approved for swapping.\\n /// @param _dexs The addresses of the DEX contracts to be approved.\\n function batchAddDex(address[] calldata _dexs) external {\\n if (msg.sender != LibDiamond.contractOwner()) {\\n LibAccess.enforceAccessControl();\\n }\\n uint256 length = _dexs.length;\\n\\n for (uint256 i = 0; i < length; ) {\\n address dex = _dexs[i];\\n if (dex == address(this)) {\\n revert CannotAuthoriseSelf();\\n }\\n if (LibAllowList.contractIsAllowed(dex)) continue;\\n LibAllowList.addAllowedContract(dex);\\n emit DexAdded(dex);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Unregister the address of a DEX contract approved for swapping.\\n /// @param _dex The address of the DEX contract to be unregistered.\\n function removeDex(address _dex) external {\\n if (msg.sender != LibDiamond.contractOwner()) {\\n LibAccess.enforceAccessControl();\\n }\\n LibAllowList.removeAllowedContract(_dex);\\n emit DexRemoved(_dex);\\n }\\n\\n /// @notice Batch unregister the addresses of DEX contracts approved for swapping.\\n /// @param _dexs The addresses of the DEX contracts to be unregistered.\\n function batchRemoveDex(address[] calldata _dexs) external {\\n if (msg.sender != LibDiamond.contractOwner()) {\\n LibAccess.enforceAccessControl();\\n }\\n uint256 length = _dexs.length;\\n for (uint256 i = 0; i < length; ) {\\n LibAllowList.removeAllowedContract(_dexs[i]);\\n emit DexRemoved(_dexs[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Adds/removes a specific function signature to/from the allowlist\\n /// @param _signature the function signature to allow/disallow\\n /// @param _approval whether the function signature should be allowed\\n function setFunctionApprovalBySignature(\\n bytes4 _signature,\\n bool _approval\\n ) external {\\n if (msg.sender != LibDiamond.contractOwner()) {\\n LibAccess.enforceAccessControl();\\n }\\n\\n if (_approval) {\\n LibAllowList.addAllowedSelector(_signature);\\n } else {\\n LibAllowList.removeAllowedSelector(_signature);\\n }\\n\\n emit FunctionSignatureApprovalChanged(_signature, _approval);\\n }\\n\\n /// @notice Batch Adds/removes a specific function signature to/from the allowlist\\n /// @param _signatures the function signatures to allow/disallow\\n /// @param _approval whether the function signatures should be allowed\\n function batchSetFunctionApprovalBySignature(\\n bytes4[] calldata _signatures,\\n bool _approval\\n ) external {\\n if (msg.sender != LibDiamond.contractOwner()) {\\n LibAccess.enforceAccessControl();\\n }\\n uint256 length = _signatures.length;\\n for (uint256 i = 0; i < length; ) {\\n bytes4 _signature = _signatures[i];\\n if (_approval) {\\n LibAllowList.addAllowedSelector(_signature);\\n } else {\\n LibAllowList.removeAllowedSelector(_signature);\\n }\\n emit FunctionSignatureApprovalChanged(_signature, _approval);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @notice Returns whether a function signature is approved\\n /// @param _signature the function signature to query\\n /// @return approved Approved or not\\n function isFunctionApproved(\\n bytes4 _signature\\n ) public view returns (bool approved) {\\n return LibAllowList.selectorIsAllowed(_signature);\\n }\\n\\n /// @notice Returns a list of all approved DEX addresses.\\n /// @return addresses List of approved DEX addresses\\n function approvedDexs()\\n external\\n view\\n returns (address[] memory addresses)\\n {\\n return LibAllowList.getAllowedContracts();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAccess.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { CannotAuthoriseSelf, UnAuthorized } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Access Library\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for managing method level access control\\nlibrary LibAccess {\\n /// Types ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.access.management\\\");\\n\\n /// Storage ///\\n struct AccessStorage {\\n mapping(bytes4 => mapping(address => bool)) execAccess;\\n }\\n\\n /// Events ///\\n event AccessGranted(address indexed account, bytes4 indexed method);\\n event AccessRevoked(address indexed account, bytes4 indexed method);\\n\\n /// @dev Fetch local storage\\n function accessStorage()\\n internal\\n pure\\n returns (AccessStorage storage accStor)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n accStor.slot := position\\n }\\n }\\n\\n /// @notice Gives an address permission to execute a method\\n /// @param selector The method selector to execute\\n /// @param executor The address to grant permission to\\n function addAccess(bytes4 selector, address executor) internal {\\n if (executor == address(this)) {\\n revert CannotAuthoriseSelf();\\n }\\n AccessStorage storage accStor = accessStorage();\\n accStor.execAccess[selector][executor] = true;\\n emit AccessGranted(executor, selector);\\n }\\n\\n /// @notice Revokes permission to execute a method\\n /// @param selector The method selector to execute\\n /// @param executor The address to revoke permission from\\n function removeAccess(bytes4 selector, address executor) internal {\\n AccessStorage storage accStor = accessStorage();\\n accStor.execAccess[selector][executor] = false;\\n emit AccessRevoked(executor, selector);\\n }\\n\\n /// @notice Enforces access control by reverting if `msg.sender`\\n /// has not been given permission to execute `msg.sig`\\n function enforceAccessControl() internal view {\\n AccessStorage storage accStor = accessStorage();\\n if (accStor.execAccess[msg.sig][msg.sender] != true)\\n revert UnAuthorized();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n\\n function revertWith(bytes memory data) internal pure {\\n assembly {\\n let dataSize := mload(data) // Load the size of the data\\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\\n revert(dataPtr, dataSize) // Revert with the given data\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[],\"name\":\"CannotAuthoriseSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnAuthorized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dexAddress\",\"type\":\"address\"}],\"name\":\"DexAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dexAddress\",\"type\":\"address\"}],\"name\":\"DexRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"functionSignature\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"FunctionSignatureApprovalChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dex\",\"type\":\"address\"}],\"name\":\"addDex\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"approvedDexs\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_dexs\",\"type\":\"address[]\"}],\"name\":\"batchAddDex\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_dexs\",\"type\":\"address[]\"}],\"name\":\"batchRemoveDex\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4[]\",\"name\":\"_signatures\",\"type\":\"bytes4[]\"},{\"internalType\":\"bool\",\"name\":\"_approval\",\"type\":\"bool\"}],\"name\":\"batchSetFunctionApprovalBySignature\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_signature\",\"type\":\"bytes4\"}],\"name\":\"isFunctionApproved\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dex\",\"type\":\"address\"}],\"name\":\"removeDex\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_signature\",\"type\":\"bytes4\"},{\"internalType\":\"bool\",\"name\":\"_approval\",\"type\":\"bool\"}],\"name\":\"setFunctionApprovalBySignature\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ContractName: "DexManagerFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/DexManagerFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { LibAccess } from \"../Libraries/LibAccess.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { CannotAuthoriseSelf } from \"../Errors/GenericErrors.sol\";\n\n/// @title Dex Manager Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Facet contract for managing approved DEXs to be used in swaps.\n/// @custom:version 1.0.1\ncontract DexManagerFacet {\n /// Events ///\n\n event DexAdded(address indexed dexAddress);\n event DexRemoved(address indexed dexAddress);\n event FunctionSignatureApprovalChanged(\n bytes4 indexed functionSignature,\n bool indexed approved\n );\n\n /// External Methods ///\n\n /// @notice Register the address of a DEX contract to be approved for swapping.\n /// @param _dex The address of the DEX contract to be approved.\n function addDex(address _dex) external {\n if (msg.sender != LibDiamond.contractOwner()) {\n LibAccess.enforceAccessControl();\n }\n\n LibAllowList.addAllowedContract(_dex);\n\n emit DexAdded(_dex);\n }\n\n /// @notice Batch register the address of DEX contracts to be approved for swapping.\n /// @param _dexs The addresses of the DEX contracts to be approved.\n function batchAddDex(address[] calldata _dexs) external {\n if (msg.sender != LibDiamond.contractOwner()) {\n LibAccess.enforceAccessControl();\n }\n uint256 length = _dexs.length;\n\n for (uint256 i = 0; i < length; ) {\n address dex = _dexs[i];\n if (dex == address(this)) {\n revert CannotAuthoriseSelf();\n }\n if (LibAllowList.contractIsAllowed(dex)) continue;\n LibAllowList.addAllowedContract(dex);\n emit DexAdded(dex);\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Unregister the address of a DEX contract approved for swapping.\n /// @param _dex The address of the DEX contract to be unregistered.\n function removeDex(address _dex) external {\n if (msg.sender != LibDiamond.contractOwner()) {\n LibAccess.enforceAccessControl();\n }\n LibAllowList.removeAllowedContract(_dex);\n emit DexRemoved(_dex);\n }\n\n /// @notice Batch unregister the addresses of DEX contracts approved for swapping.\n /// @param _dexs The addresses of the DEX contracts to be unregistered.\n function batchRemoveDex(address[] calldata _dexs) external {\n if (msg.sender != LibDiamond.contractOwner()) {\n LibAccess.enforceAccessControl();\n }\n uint256 length = _dexs.length;\n for (uint256 i = 0; i < length; ) {\n LibAllowList.removeAllowedContract(_dexs[i]);\n emit DexRemoved(_dexs[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Adds/removes a specific function signature to/from the allowlist\n /// @param _signature the function signature to allow/disallow\n /// @param _approval whether the function signature should be allowed\n function setFunctionApprovalBySignature(\n bytes4 _signature,\n bool _approval\n ) external {\n if (msg.sender != LibDiamond.contractOwner()) {\n LibAccess.enforceAccessControl();\n }\n\n if (_approval) {\n LibAllowList.addAllowedSelector(_signature);\n } else {\n LibAllowList.removeAllowedSelector(_signature);\n }\n\n emit FunctionSignatureApprovalChanged(_signature, _approval);\n }\n\n /// @notice Batch Adds/removes a specific function signature to/from the allowlist\n /// @param _signatures the function signatures to allow/disallow\n /// @param _approval whether the function signatures should be allowed\n function batchSetFunctionApprovalBySignature(\n bytes4[] calldata _signatures,\n bool _approval\n ) external {\n if (msg.sender != LibDiamond.contractOwner()) {\n LibAccess.enforceAccessControl();\n }\n uint256 length = _signatures.length;\n for (uint256 i = 0; i < length; ) {\n bytes4 _signature = _signatures[i];\n if (_approval) {\n LibAllowList.addAllowedSelector(_signature);\n } else {\n LibAllowList.removeAllowedSelector(_signature);\n }\n emit FunctionSignatureApprovalChanged(_signature, _approval);\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Returns whether a function signature is approved\n /// @param _signature the function signature to query\n /// @return approved Approved or not\n function isFunctionApproved(\n bytes4 _signature\n ) public view returns (bool approved) {\n return LibAllowList.selectorIsAllowed(_signature);\n }\n\n /// @notice Returns a list of all approved DEX addresses.\n /// @return addresses List of approved DEX addresses\n function approvedDexs()\n external\n view\n returns (address[] memory addresses)\n {\n return LibAllowList.getAllowedContracts();\n }\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Libraries/LibAccess.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { CannotAuthoriseSelf, UnAuthorized } from \"../Errors/GenericErrors.sol\";\n\n/// @title Access Library\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for managing method level access control\nlibrary LibAccess {\n /// Types ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.access.management\");\n\n /// Storage ///\n struct AccessStorage {\n mapping(bytes4 => mapping(address => bool)) execAccess;\n }\n\n /// Events ///\n event AccessGranted(address indexed account, bytes4 indexed method);\n event AccessRevoked(address indexed account, bytes4 indexed method);\n\n /// @dev Fetch local storage\n function accessStorage()\n internal\n pure\n returns (AccessStorage storage accStor)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n accStor.slot := position\n }\n }\n\n /// @notice Gives an address permission to execute a method\n /// @param selector The method selector to execute\n /// @param executor The address to grant permission to\n function addAccess(bytes4 selector, address executor) internal {\n if (executor == address(this)) {\n revert CannotAuthoriseSelf();\n }\n AccessStorage storage accStor = accessStorage();\n accStor.execAccess[selector][executor] = true;\n emit AccessGranted(executor, selector);\n }\n\n /// @notice Revokes permission to execute a method\n /// @param selector The method selector to execute\n /// @param executor The address to revoke permission from\n function removeAccess(bytes4 selector, address executor) internal {\n AccessStorage storage accStor = accessStorage();\n accStor.execAccess[selector][executor] = false;\n emit AccessRevoked(executor, selector);\n }\n\n /// @notice Enforces access control by reverting if `msg.sender`\n /// has not been given permission to execute `msg.sig`\n function enforceAccessControl() internal view {\n AccessStorage storage accStor = accessStorage();\n if (accStor.execAccess[msg.sig][msg.sender] != true)\n revert UnAuthorized();\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n\n function revertWith(bytes memory data) internal pure {\n assembly {\n let dataSize := mload(data) // Load the size of the data\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\n revert(dataPtr, dataSize) // Revert with the given data\n }\n }\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +1.0.1 + Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \AccessManagerFacet +0x77a13abb679a0dafb4435d1fa4ccc95d1ab51cfc +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/AccessManagerFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { LibAccess } from \\\"../Libraries/LibAccess.sol\\\";\\nimport { CannotAuthoriseSelf } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Access Manager Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for managing method level access control\\n/// @custom:version 1.0.0\\ncontract AccessManagerFacet {\\n /// Events ///\\n\\n event ExecutionAllowed(address indexed account, bytes4 indexed method);\\n event ExecutionDenied(address indexed account, bytes4 indexed method);\\n\\n /// External Methods ///\\n\\n /// @notice Sets whether a specific address can call a method\\n /// @param _selector The method selector to set access for\\n /// @param _executor The address to set method access for\\n /// @param _canExecute Whether or not the address can execute the specified method\\n function setCanExecute(\\n bytes4 _selector,\\n address _executor,\\n bool _canExecute\\n ) external {\\n if (_executor == address(this)) {\\n revert CannotAuthoriseSelf();\\n }\\n LibDiamond.enforceIsContractOwner();\\n _canExecute\\n ? LibAccess.addAccess(_selector, _executor)\\n : LibAccess.removeAccess(_selector, _executor);\\n if (_canExecute) {\\n emit ExecutionAllowed(_executor, _selector);\\n } else {\\n emit ExecutionDenied(_executor, _selector);\\n }\\n }\\n\\n /// @notice Check if a method can be executed by a specific address\\n /// @param _selector The method selector to check\\n /// @param _executor The address to check\\n function addressCanExecuteMethod(\\n bytes4 _selector,\\n address _executor\\n ) external view returns (bool) {\\n return LibAccess.accessStorage().execAccess[_selector][_executor];\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAccess.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { CannotAuthoriseSelf, UnAuthorized } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Access Library\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for managing method level access control\\nlibrary LibAccess {\\n /// Types ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.access.management\\\");\\n\\n /// Storage ///\\n struct AccessStorage {\\n mapping(bytes4 => mapping(address => bool)) execAccess;\\n }\\n\\n /// Events ///\\n event AccessGranted(address indexed account, bytes4 indexed method);\\n event AccessRevoked(address indexed account, bytes4 indexed method);\\n\\n /// @dev Fetch local storage\\n function accessStorage()\\n internal\\n pure\\n returns (AccessStorage storage accStor)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n accStor.slot := position\\n }\\n }\\n\\n /// @notice Gives an address permission to execute a method\\n /// @param selector The method selector to execute\\n /// @param executor The address to grant permission to\\n function addAccess(bytes4 selector, address executor) internal {\\n if (executor == address(this)) {\\n revert CannotAuthoriseSelf();\\n }\\n AccessStorage storage accStor = accessStorage();\\n accStor.execAccess[selector][executor] = true;\\n emit AccessGranted(executor, selector);\\n }\\n\\n /// @notice Revokes permission to execute a method\\n /// @param selector The method selector to execute\\n /// @param executor The address to revoke permission from\\n function removeAccess(bytes4 selector, address executor) internal {\\n AccessStorage storage accStor = accessStorage();\\n accStor.execAccess[selector][executor] = false;\\n emit AccessRevoked(executor, selector);\\n }\\n\\n /// @notice Enforces access control by reverting if `msg.sender`\\n /// has not been given permission to execute `msg.sig`\\n function enforceAccessControl() internal view {\\n AccessStorage storage accStor = accessStorage();\\n if (accStor.execAccess[msg.sig][msg.sender] != true)\\n revert UnAuthorized();\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[],\"name\":\"CannotAuthoriseSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyContractOwner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"method\",\"type\":\"bytes4\"}],\"name\":\"ExecutionAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"method\",\"type\":\"bytes4\"}],\"name\":\"ExecutionDenied\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_selector\",\"type\":\"bytes4\"},{\"internalType\":\"address\",\"name\":\"_executor\",\"type\":\"address\"}],\"name\":\"addressCanExecuteMethod\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_selector\",\"type\":\"bytes4\"},{\"internalType\":\"address\",\"name\":\"_executor\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_canExecute\",\"type\":\"bool\"}],\"name\":\"setCanExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ContractName: "AccessManagerFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/AccessManagerFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { LibAccess } from \"../Libraries/LibAccess.sol\";\nimport { CannotAuthoriseSelf } from \"../Errors/GenericErrors.sol\";\n\n/// @title Access Manager Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for managing method level access control\n/// @custom:version 1.0.0\ncontract AccessManagerFacet {\n /// Events ///\n\n event ExecutionAllowed(address indexed account, bytes4 indexed method);\n event ExecutionDenied(address indexed account, bytes4 indexed method);\n\n /// External Methods ///\n\n /// @notice Sets whether a specific address can call a method\n /// @param _selector The method selector to set access for\n /// @param _executor The address to set method access for\n /// @param _canExecute Whether or not the address can execute the specified method\n function setCanExecute(\n bytes4 _selector,\n address _executor,\n bool _canExecute\n ) external {\n if (_executor == address(this)) {\n revert CannotAuthoriseSelf();\n }\n LibDiamond.enforceIsContractOwner();\n _canExecute\n ? LibAccess.addAccess(_selector, _executor)\n : LibAccess.removeAccess(_selector, _executor);\n if (_canExecute) {\n emit ExecutionAllowed(_executor, _selector);\n } else {\n emit ExecutionDenied(_executor, _selector);\n }\n }\n\n /// @notice Check if a method can be executed by a specific address\n /// @param _selector The method selector to check\n /// @param _executor The address to check\n function addressCanExecuteMethod(\n bytes4 _selector,\n address _executor\n ) external view returns (bool) {\n return LibAccess.accessStorage().execAccess[_selector][_executor];\n }\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Libraries/LibAccess.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { CannotAuthoriseSelf, UnAuthorized } from \"../Errors/GenericErrors.sol\";\n\n/// @title Access Library\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for managing method level access control\nlibrary LibAccess {\n /// Types ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.access.management\");\n\n /// Storage ///\n struct AccessStorage {\n mapping(bytes4 => mapping(address => bool)) execAccess;\n }\n\n /// Events ///\n event AccessGranted(address indexed account, bytes4 indexed method);\n event AccessRevoked(address indexed account, bytes4 indexed method);\n\n /// @dev Fetch local storage\n function accessStorage()\n internal\n pure\n returns (AccessStorage storage accStor)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n accStor.slot := position\n }\n }\n\n /// @notice Gives an address permission to execute a method\n /// @param selector The method selector to execute\n /// @param executor The address to grant permission to\n function addAccess(bytes4 selector, address executor) internal {\n if (executor == address(this)) {\n revert CannotAuthoriseSelf();\n }\n AccessStorage storage accStor = accessStorage();\n accStor.execAccess[selector][executor] = true;\n emit AccessGranted(executor, selector);\n }\n\n /// @notice Revokes permission to execute a method\n /// @param selector The method selector to execute\n /// @param executor The address to revoke permission from\n function removeAccess(bytes4 selector, address executor) internal {\n AccessStorage storage accStor = accessStorage();\n accStor.execAccess[selector][executor] = false;\n emit AccessRevoked(executor, selector);\n }\n\n /// @notice Enforces access control by reverting if `msg.sender`\n /// has not been given permission to execute `msg.sig`\n function enforceAccessControl() internal view {\n AccessStorage storage accStor = accessStorage();\n if (accStor.execAccess[msg.sig][msg.sender] != true)\n revert UnAuthorized();\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... -AmarokFacet +0x3f95b05a77fdc6d82162d86a72b156b55030627f +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/AmarokFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IConnextHandler } from \\\"../Interfaces/IConnextHandler.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { InformationMismatch } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title Amarok Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Connext Amarok\\n/// @custom:version 3.0.0\\ncontract AmarokFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n /// @notice The contract address of the connext handler on the source chain.\\n IConnextHandler private immutable connextHandler;\\n\\n /// @param callData The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.\\n /// @param callTo The address of the contract on dest chain that will receive bridged funds and execute data\\n /// @param relayerFee The amount of relayer fee the tx called xcall with\\n /// @param slippageTol Maximum acceptable slippage in BPS. For example, a value of 30 means 0.3% slippage\\n /// @param delegate Destination delegate address\\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\\n /// @param payFeeWithSendingAsset Whether to pay the relayer fee with the sending asset or not\\n struct AmarokData {\\n bytes callData;\\n address callTo;\\n uint256 relayerFee;\\n uint256 slippageTol;\\n address delegate;\\n uint32 destChainDomainId;\\n bool payFeeWithSendingAsset;\\n }\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _connextHandler The contract address of the connext handler on the source chain.\\n constructor(IConnextHandler _connextHandler) {\\n connextHandler = _connextHandler;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Amarok\\n /// @param _bridgeData Data containing core information for bridging\\n /// @param _amarokData Data specific to bridge\\n function startBridgeTokensViaAmarok(\\n BridgeData calldata _bridgeData,\\n AmarokData calldata _amarokData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n noNativeAsset(_bridgeData)\\n {\\n validateDestinationCallFlag(_bridgeData, _amarokData);\\n\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n\\n _startBridge(_bridgeData, _amarokData);\\n }\\n\\n /// @notice Performs a swap before bridging via Amarok\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _amarokData Data specific to Amarok\\n function swapAndStartBridgeTokensViaAmarok(\\n BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n AmarokData calldata _amarokData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n noNativeAsset(_bridgeData)\\n {\\n validateDestinationCallFlag(_bridgeData, _amarokData);\\n\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n _amarokData.relayerFee\\n );\\n\\n _startBridge(_bridgeData, _amarokData);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Amarok\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _amarokData Data specific to Amarok\\n function _startBridge(\\n BridgeData memory _bridgeData,\\n AmarokData calldata _amarokData\\n ) private {\\n // ensure that receiver addresses match in case of no destination call\\n if (\\n !_bridgeData.hasDestinationCall &&\\n (_bridgeData.receiver != _amarokData.callTo)\\n ) revert InformationMismatch();\\n\\n // give max approval for token to Amarok bridge, if not already\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(connextHandler),\\n _bridgeData.minAmount\\n );\\n\\n // initiate bridge transaction\\n if (_amarokData.payFeeWithSendingAsset) {\\n connextHandler.xcall(\\n _amarokData.destChainDomainId,\\n _amarokData.callTo,\\n _bridgeData.sendingAssetId,\\n _amarokData.delegate,\\n _bridgeData.minAmount - _amarokData.relayerFee,\\n _amarokData.slippageTol,\\n _amarokData.callData,\\n _amarokData.relayerFee\\n );\\n } else {\\n connextHandler.xcall{ value: _amarokData.relayerFee }(\\n _amarokData.destChainDomainId,\\n _amarokData.callTo,\\n _bridgeData.sendingAssetId,\\n _amarokData.delegate,\\n _bridgeData.minAmount,\\n _amarokData.slippageTol,\\n _amarokData.callData\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n function validateDestinationCallFlag(\\n ILiFi.BridgeData memory _bridgeData,\\n AmarokData calldata _amarokData\\n ) private pure {\\n if (\\n (_amarokData.callData.length > 0) != _bridgeData.hasDestinationCall\\n ) {\\n revert InformationMismatch();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IConnextHandler.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IConnextHandler {\\n /// @notice These are the call parameters that will remain constant between the\\n /// two chains. They are supplied on `xcall` and should be asserted on `execute`\\n /// @property to - The account that receives funds, in the event of a crosschain call,\\n /// will receive funds if the call fails.\\n /// @param to - The address you are sending funds (and potentially data) to\\n /// @param callData - The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.\\n /// @param originDomain - The originating domain (i.e. where `xcall` is called). Must match nomad domain schema\\n /// @param destinationDomain - The final domain (i.e. where `execute` / `reconcile` are called). Must match nomad domain schema\\n /// @param agent - An address who can execute txs on behalf of `to`, in addition to allowing relayers\\n /// @param recovery - The address to send funds to if your `Executor.execute call` fails\\n /// @param forceSlow - If true, will take slow liquidity path even if it is not a permissioned call\\n /// @param receiveLocal - If true, will use the local nomad asset on the destination instead of adopted.\\n /// @param callback - The address on the origin domain of the callback contract\\n /// @param callbackFee - The relayer fee to execute the callback\\n /// @param relayerFee - The amount of relayer fee the tx called xcall with\\n /// @param slippageTol - Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)\\n struct CallParams {\\n address to;\\n bytes callData;\\n uint32 originDomain;\\n uint32 destinationDomain;\\n address agent;\\n address recovery;\\n bool forceSlow;\\n bool receiveLocal;\\n address callback;\\n uint256 callbackFee;\\n uint256 relayerFee;\\n uint256 slippageTol;\\n }\\n\\n /// @notice The arguments you supply to the `xcall` function called by user on origin domain\\n /// @param params - The CallParams. These are consistent across sending and receiving chains\\n /// @param transactingAsset - The asset the caller sent with the transfer. Can be the adopted, canonical,\\n /// or the representational asset\\n /// @param transactingAmount - The amount of transferring asset supplied by the user in the `xcall`\\n /// @param originMinOut - Minimum amount received on swaps for adopted <> local on origin chain\\n struct XCallArgs {\\n CallParams params;\\n address transactingAsset; // Could be adopted, local, or wrapped\\n uint256 transactingAmount;\\n uint256 originMinOut;\\n }\\n\\n function xcall(\\n uint32 destination,\\n address recipient,\\n address tokenAddress,\\n address delegate,\\n uint256 amount,\\n uint256 slippage,\\n bytes memory callData\\n ) external payable returns (bytes32);\\n\\n function xcall(\\n uint32 destination,\\n address recipient,\\n address tokenAddress,\\n address delegate,\\n uint256 amount,\\n uint256 slippage,\\n bytes memory callData,\\n uint256 _relayerFee\\n ) external returns (bytes32);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n LibUtil.revertWith(res);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n\\n function revertWith(bytes memory data) internal pure {\\n assembly {\\n let dataSize := mload(data) // Load the size of the data\\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\\n revert(dataPtr, dataSize) // Revert with the given data\\n }\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IConnextHandler\",\"name\":\"_connextHandler\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"slippageTol\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destChainDomainId\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"payFeeWithSendingAsset\",\"type\":\"bool\"}],\"internalType\":\"struct AmarokFacet.AmarokData\",\"name\":\"_amarokData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaAmarok\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"slippageTol\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destChainDomainId\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"payFeeWithSendingAsset\",\"type\":\"bool\"}],\"internalType\":\"struct AmarokFacet.AmarokData\",\"name\":\"_amarokData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaAmarok\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "AmarokFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000008898b472c54c31894e3b9bb83cea802a5d0e63c6", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/AmarokFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IConnextHandler } from \"../Interfaces/IConnextHandler.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { InformationMismatch } from \"../Errors/GenericErrors.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title Amarok Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Connext Amarok\n/// @custom:version 3.0.0\ncontract AmarokFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n /// @notice The contract address of the connext handler on the source chain.\n IConnextHandler private immutable connextHandler;\n\n /// @param callData The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.\n /// @param callTo The address of the contract on dest chain that will receive bridged funds and execute data\n /// @param relayerFee The amount of relayer fee the tx called xcall with\n /// @param slippageTol Maximum acceptable slippage in BPS. For example, a value of 30 means 0.3% slippage\n /// @param delegate Destination delegate address\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\n /// @param payFeeWithSendingAsset Whether to pay the relayer fee with the sending asset or not\n struct AmarokData {\n bytes callData;\n address callTo;\n uint256 relayerFee;\n uint256 slippageTol;\n address delegate;\n uint32 destChainDomainId;\n bool payFeeWithSendingAsset;\n }\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _connextHandler The contract address of the connext handler on the source chain.\n constructor(IConnextHandler _connextHandler) {\n connextHandler = _connextHandler;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Amarok\n /// @param _bridgeData Data containing core information for bridging\n /// @param _amarokData Data specific to bridge\n function startBridgeTokensViaAmarok(\n BridgeData calldata _bridgeData,\n AmarokData calldata _amarokData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n noNativeAsset(_bridgeData)\n {\n validateDestinationCallFlag(_bridgeData, _amarokData);\n\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n\n _startBridge(_bridgeData, _amarokData);\n }\n\n /// @notice Performs a swap before bridging via Amarok\n /// @param _bridgeData The core information needed for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _amarokData Data specific to Amarok\n function swapAndStartBridgeTokensViaAmarok(\n BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n AmarokData calldata _amarokData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n noNativeAsset(_bridgeData)\n {\n validateDestinationCallFlag(_bridgeData, _amarokData);\n\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n _amarokData.relayerFee\n );\n\n _startBridge(_bridgeData, _amarokData);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via Amarok\n /// @param _bridgeData The core information needed for bridging\n /// @param _amarokData Data specific to Amarok\n function _startBridge(\n BridgeData memory _bridgeData,\n AmarokData calldata _amarokData\n ) private {\n // ensure that receiver addresses match in case of no destination call\n if (\n !_bridgeData.hasDestinationCall &&\n (_bridgeData.receiver != _amarokData.callTo)\n ) revert InformationMismatch();\n\n // give max approval for token to Amarok bridge, if not already\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(connextHandler),\n _bridgeData.minAmount\n );\n\n // initiate bridge transaction\n if (_amarokData.payFeeWithSendingAsset) {\n connextHandler.xcall(\n _amarokData.destChainDomainId,\n _amarokData.callTo,\n _bridgeData.sendingAssetId,\n _amarokData.delegate,\n _bridgeData.minAmount - _amarokData.relayerFee,\n _amarokData.slippageTol,\n _amarokData.callData,\n _amarokData.relayerFee\n );\n } else {\n connextHandler.xcall{ value: _amarokData.relayerFee }(\n _amarokData.destChainDomainId,\n _amarokData.callTo,\n _bridgeData.sendingAssetId,\n _amarokData.delegate,\n _bridgeData.minAmount,\n _amarokData.slippageTol,\n _amarokData.callData\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n function validateDestinationCallFlag(\n ILiFi.BridgeData memory _bridgeData,\n AmarokData calldata _amarokData\n ) private pure {\n if (\n (_amarokData.callData.length > 0) != _bridgeData.hasDestinationCall\n ) {\n revert InformationMismatch();\n }\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IConnextHandler.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IConnextHandler {\n /// @notice These are the call parameters that will remain constant between the\n /// two chains. They are supplied on `xcall` and should be asserted on `execute`\n /// @property to - The account that receives funds, in the event of a crosschain call,\n /// will receive funds if the call fails.\n /// @param to - The address you are sending funds (and potentially data) to\n /// @param callData - The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.\n /// @param originDomain - The originating domain (i.e. where `xcall` is called). Must match nomad domain schema\n /// @param destinationDomain - The final domain (i.e. where `execute` / `reconcile` are called). Must match nomad domain schema\n /// @param agent - An address who can execute txs on behalf of `to`, in addition to allowing relayers\n /// @param recovery - The address to send funds to if your `Executor.execute call` fails\n /// @param forceSlow - If true, will take slow liquidity path even if it is not a permissioned call\n /// @param receiveLocal - If true, will use the local nomad asset on the destination instead of adopted.\n /// @param callback - The address on the origin domain of the callback contract\n /// @param callbackFee - The relayer fee to execute the callback\n /// @param relayerFee - The amount of relayer fee the tx called xcall with\n /// @param slippageTol - Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)\n struct CallParams {\n address to;\n bytes callData;\n uint32 originDomain;\n uint32 destinationDomain;\n address agent;\n address recovery;\n bool forceSlow;\n bool receiveLocal;\n address callback;\n uint256 callbackFee;\n uint256 relayerFee;\n uint256 slippageTol;\n }\n\n /// @notice The arguments you supply to the `xcall` function called by user on origin domain\n /// @param params - The CallParams. These are consistent across sending and receiving chains\n /// @param transactingAsset - The asset the caller sent with the transfer. Can be the adopted, canonical,\n /// or the representational asset\n /// @param transactingAmount - The amount of transferring asset supplied by the user in the `xcall`\n /// @param originMinOut - Minimum amount received on swaps for adopted <> local on origin chain\n struct XCallArgs {\n CallParams params;\n address transactingAsset; // Could be adopted, local, or wrapped\n uint256 transactingAmount;\n uint256 originMinOut;\n }\n\n function xcall(\n uint32 destination,\n address recipient,\n address tokenAddress,\n address delegate,\n uint256 amount,\n uint256 slippage,\n bytes memory callData\n ) external payable returns (bytes32);\n\n function xcall(\n uint32 destination,\n address recipient,\n address tokenAddress,\n address delegate,\n uint256 amount,\n uint256 slippage,\n bytes memory callData,\n uint256 _relayerFee\n ) external returns (bytes32);\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n LibUtil.revertWith(res);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n\n function revertWith(bytes memory data) internal pure {\n assembly {\n let dataSize := mload(data) // Load the size of the data\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\n revert(dataPtr, dataSize) // Revert with the given data\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +3.0.0 + Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... /CBridgeFacet +0x3b70eb33948fbfdc3f2f2491b96dfb1aa18054e0 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/CBridgeFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAccess } from \\\"../Libraries/LibAccess.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { ICBridge } from \\\"../Interfaces/ICBridge.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { ContractCallNotAllowed, ExternalCallFailed } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title CBridge Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through CBridge\\n/// @custom:version 1.0.0\\ncontract CBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n /// @notice The contract address of the cbridge on the source chain.\\n ICBridge private immutable cBridge;\\n\\n /// Types ///\\n\\n /// @param maxSlippage The max slippage accepted, given as percentage in point (pip).\\n /// @param nonce A number input to guarantee uniqueness of transferId.\\n /// Can be timestamp in practice.\\n struct CBridgeData {\\n uint32 maxSlippage;\\n uint64 nonce;\\n }\\n\\n /// Events ///\\n event CBridgeRefund(\\n address indexed _assetAddress,\\n address indexed _to,\\n uint256 amount\\n );\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _cBridge The contract address of the cbridge on the source chain.\\n constructor(ICBridge _cBridge) {\\n cBridge = _cBridge;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via CBridge\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _cBridgeData data specific to CBridge\\n function startBridgeTokensViaCBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n CBridgeData calldata _cBridgeData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData, _cBridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging via CBridge\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _cBridgeData data specific to CBridge\\n function swapAndStartBridgeTokensViaCBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n CBridgeData calldata _cBridgeData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n _startBridge(_bridgeData, _cBridgeData);\\n }\\n\\n /// @notice Triggers a cBridge refund with calldata produced by cBridge API\\n /// @param _callTo The address to execute the calldata on\\n /// @param _callData The data to execute\\n /// @param _assetAddress Asset to be withdrawn\\n /// @param _to Address to withdraw to\\n /// @param _amount Amount of asset to withdraw\\n function triggerRefund(\\n address payable _callTo,\\n bytes calldata _callData,\\n address _assetAddress,\\n address _to,\\n uint256 _amount\\n ) external {\\n if (msg.sender != LibDiamond.contractOwner()) {\\n LibAccess.enforceAccessControl();\\n }\\n\\n // make sure that callTo address is either of the cBridge addresses\\n if (address(cBridge) != _callTo) {\\n revert ContractCallNotAllowed();\\n }\\n\\n // call contract\\n bool success;\\n (success, ) = _callTo.call(_callData);\\n if (!success) {\\n revert ExternalCallFailed();\\n }\\n\\n // forward funds to _to address and emit event\\n address sendTo = (LibUtil.isZeroAddress(_to)) ? msg.sender : _to;\\n LibAsset.transferAsset(_assetAddress, payable(sendTo), _amount);\\n emit CBridgeRefund(_assetAddress, sendTo, _amount);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via CBridge\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _cBridgeData data specific to CBridge\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n CBridgeData calldata _cBridgeData\\n ) private {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n cBridge.sendNative{ value: _bridgeData.minAmount }(\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _cBridgeData.nonce,\\n _cBridgeData.maxSlippage\\n );\\n } else {\\n // Give CBridge approval to bridge tokens\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(cBridge),\\n _bridgeData.minAmount\\n );\\n // solhint-disable check-send-result\\n cBridge.send(\\n _bridgeData.receiver,\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _cBridgeData.nonce,\\n _cBridgeData.maxSlippage\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAccess.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { CannotAuthoriseSelf, UnAuthorized } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Access Library\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for managing method level access control\\nlibrary LibAccess {\\n /// Types ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.access.management\\\");\\n\\n /// Storage ///\\n struct AccessStorage {\\n mapping(bytes4 => mapping(address => bool)) execAccess;\\n }\\n\\n /// Events ///\\n event AccessGranted(address indexed account, bytes4 indexed method);\\n event AccessRevoked(address indexed account, bytes4 indexed method);\\n\\n /// @dev Fetch local storage\\n function accessStorage()\\n internal\\n pure\\n returns (AccessStorage storage accStor)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n accStor.slot := position\\n }\\n }\\n\\n /// @notice Gives an address permission to execute a method\\n /// @param selector The method selector to execute\\n /// @param executor The address to grant permission to\\n function addAccess(bytes4 selector, address executor) internal {\\n if (executor == address(this)) {\\n revert CannotAuthoriseSelf();\\n }\\n AccessStorage storage accStor = accessStorage();\\n accStor.execAccess[selector][executor] = true;\\n emit AccessGranted(executor, selector);\\n }\\n\\n /// @notice Revokes permission to execute a method\\n /// @param selector The method selector to execute\\n /// @param executor The address to revoke permission from\\n function removeAccess(bytes4 selector, address executor) internal {\\n AccessStorage storage accStor = accessStorage();\\n accStor.execAccess[selector][executor] = false;\\n emit AccessRevoked(executor, selector);\\n }\\n\\n /// @notice Enforces access control by reverting if `msg.sender`\\n /// has not been given permission to execute `msg.sig`\\n function enforceAccessControl() internal view {\\n AccessStorage storage accStor = accessStorage();\\n if (accStor.execAccess[msg.sig][msg.sender] != true)\\n revert UnAuthorized();\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/ICBridge.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ICBridge {\\n /// @notice Send a cross-chain transfer via the liquidity pool-based bridge.\\n /// @dev This function DOES NOT SUPPORT fee-on-transfer / rebasing tokens.\\n /// @param _receiver The address of the receiver.\\n /// @param _token The address of the token.\\n /// @param _amount The amount of the transfer.\\n /// @param _dstChainId The destination chain ID.\\n /// @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\\n /// @param _maxSlippage The max slippage accepted, given as percentage in point (pip).\\n /// Eg. 5000 means 0.5%. Must be greater than minimalMaxSlippage.\\n /// Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount\\n /// or the transfer can be refunded.\\n function send(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce,\\n uint32 _maxSlippage\\n ) external;\\n\\n /// @notice Send a cross-chain transfer via the liquidity pool-based bridge using the native token.\\n /// @param _receiver The address of the receiver.\\n /// @param _amount The amount of the transfer.\\n /// @param _dstChainId The destination chain ID.\\n /// @param _nonce A unique number. Can be timestamp in practice.\\n /// @param _maxSlippage The max slippage accepted, given as percentage in point (pip).\\n /// Eg. 5000 means 0.5%. Must be greater than minimalMaxSlippage.\\n /// Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount\\n /// or the transfer can be refunded.\\n function sendNative(\\n address _receiver,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce,\\n uint32 _maxSlippage\\n ) external payable;\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract ICBridge\",\"name\":\"_cBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExternalCallFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnAuthorized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"CBridgeRefund\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSlippage\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"struct CBridgeFacet.CBridgeData\",\"name\":\"_cBridgeData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaCBridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSlippage\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"struct CBridgeFacet.CBridgeData\",\"name\":\"_cBridgeData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaCBridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_callTo\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_callData\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"_assetAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"triggerRefund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ContractName: "CBridgeFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000005427fefa711eff984124bfbb1ab6fbf5e3da1820", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/CBridgeFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { LibAccess } from \"../Libraries/LibAccess.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { ICBridge } from \"../Interfaces/ICBridge.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { ContractCallNotAllowed, ExternalCallFailed } from \"../Errors/GenericErrors.sol\";\n\n/// @title CBridge Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through CBridge\n/// @custom:version 1.0.0\ncontract CBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n /// @notice The contract address of the cbridge on the source chain.\n ICBridge private immutable cBridge;\n\n /// Types ///\n\n /// @param maxSlippage The max slippage accepted, given as percentage in point (pip).\n /// @param nonce A number input to guarantee uniqueness of transferId.\n /// Can be timestamp in practice.\n struct CBridgeData {\n uint32 maxSlippage;\n uint64 nonce;\n }\n\n /// Events ///\n event CBridgeRefund(\n address indexed _assetAddress,\n address indexed _to,\n uint256 amount\n );\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _cBridge The contract address of the cbridge on the source chain.\n constructor(ICBridge _cBridge) {\n cBridge = _cBridge;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via CBridge\n /// @param _bridgeData the core information needed for bridging\n /// @param _cBridgeData data specific to CBridge\n function startBridgeTokensViaCBridge(\n ILiFi.BridgeData memory _bridgeData,\n CBridgeData calldata _cBridgeData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData, _cBridgeData);\n }\n\n /// @notice Performs a swap before bridging via CBridge\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _cBridgeData data specific to CBridge\n function swapAndStartBridgeTokensViaCBridge(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n CBridgeData calldata _cBridgeData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n _startBridge(_bridgeData, _cBridgeData);\n }\n\n /// @notice Triggers a cBridge refund with calldata produced by cBridge API\n /// @param _callTo The address to execute the calldata on\n /// @param _callData The data to execute\n /// @param _assetAddress Asset to be withdrawn\n /// @param _to Address to withdraw to\n /// @param _amount Amount of asset to withdraw\n function triggerRefund(\n address payable _callTo,\n bytes calldata _callData,\n address _assetAddress,\n address _to,\n uint256 _amount\n ) external {\n if (msg.sender != LibDiamond.contractOwner()) {\n LibAccess.enforceAccessControl();\n }\n\n // make sure that callTo address is either of the cBridge addresses\n if (address(cBridge) != _callTo) {\n revert ContractCallNotAllowed();\n }\n\n // call contract\n bool success;\n (success, ) = _callTo.call(_callData);\n if (!success) {\n revert ExternalCallFailed();\n }\n\n // forward funds to _to address and emit event\n address sendTo = (LibUtil.isZeroAddress(_to)) ? msg.sender : _to;\n LibAsset.transferAsset(_assetAddress, payable(sendTo), _amount);\n emit CBridgeRefund(_assetAddress, sendTo, _amount);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via CBridge\n /// @param _bridgeData the core information needed for bridging\n /// @param _cBridgeData data specific to CBridge\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n CBridgeData calldata _cBridgeData\n ) private {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n cBridge.sendNative{ value: _bridgeData.minAmount }(\n _bridgeData.receiver,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _cBridgeData.nonce,\n _cBridgeData.maxSlippage\n );\n } else {\n // Give CBridge approval to bridge tokens\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(cBridge),\n _bridgeData.minAmount\n );\n // solhint-disable check-send-result\n cBridge.send(\n _bridgeData.receiver,\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _cBridgeData.nonce,\n _cBridgeData.maxSlippage\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Libraries/LibAccess.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { CannotAuthoriseSelf, UnAuthorized } from \"../Errors/GenericErrors.sol\";\n\n/// @title Access Library\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for managing method level access control\nlibrary LibAccess {\n /// Types ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.access.management\");\n\n /// Storage ///\n struct AccessStorage {\n mapping(bytes4 => mapping(address => bool)) execAccess;\n }\n\n /// Events ///\n event AccessGranted(address indexed account, bytes4 indexed method);\n event AccessRevoked(address indexed account, bytes4 indexed method);\n\n /// @dev Fetch local storage\n function accessStorage()\n internal\n pure\n returns (AccessStorage storage accStor)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n accStor.slot := position\n }\n }\n\n /// @notice Gives an address permission to execute a method\n /// @param selector The method selector to execute\n /// @param executor The address to grant permission to\n function addAccess(bytes4 selector, address executor) internal {\n if (executor == address(this)) {\n revert CannotAuthoriseSelf();\n }\n AccessStorage storage accStor = accessStorage();\n accStor.execAccess[selector][executor] = true;\n emit AccessGranted(executor, selector);\n }\n\n /// @notice Revokes permission to execute a method\n /// @param selector The method selector to execute\n /// @param executor The address to revoke permission from\n function removeAccess(bytes4 selector, address executor) internal {\n AccessStorage storage accStor = accessStorage();\n accStor.execAccess[selector][executor] = false;\n emit AccessRevoked(executor, selector);\n }\n\n /// @notice Enforces access control by reverting if `msg.sender`\n /// has not been given permission to execute `msg.sig`\n function enforceAccessControl() internal view {\n AccessStorage storage accStor = accessStorage();\n if (accStor.execAccess[msg.sig][msg.sender] != true)\n revert UnAuthorized();\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/ICBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ICBridge {\n /// @notice Send a cross-chain transfer via the liquidity pool-based bridge.\n /// @dev This function DOES NOT SUPPORT fee-on-transfer / rebasing tokens.\n /// @param _receiver The address of the receiver.\n /// @param _token The address of the token.\n /// @param _amount The amount of the transfer.\n /// @param _dstChainId The destination chain ID.\n /// @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\n /// @param _maxSlippage The max slippage accepted, given as percentage in point (pip).\n /// Eg. 5000 means 0.5%. Must be greater than minimalMaxSlippage.\n /// Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount\n /// or the transfer can be refunded.\n function send(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce,\n uint32 _maxSlippage\n ) external;\n\n /// @notice Send a cross-chain transfer via the liquidity pool-based bridge using the native token.\n /// @param _receiver The address of the receiver.\n /// @param _amount The amount of the transfer.\n /// @param _dstChainId The destination chain ID.\n /// @param _nonce A unique number. Can be timestamp in practice.\n /// @param _maxSlippage The max slippage accepted, given as percentage in point (pip).\n /// Eg. 5000 means 0.5%. Must be greater than minimalMaxSlippage.\n /// Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount\n /// or the transfer can be refunded.\n function sendNative(\n address _receiver,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce,\n uint32 _maxSlippage\n ) external payable;\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... |GnosisBridgeFacet +0x0ef01249e2731082a078c0b3f408c2929c90ac9c +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/GnosisBridgeFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IXDaiBridge } from \\\"../Interfaces/IXDaiBridge.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { InvalidSendingToken, NoSwapDataProvided } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title Gnosis Bridge Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through XDaiBridge\\n/// @custom:version 1.0.0\\ncontract GnosisBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n /// @notice The DAI address on the source chain.\\n address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\\n\\n /// @notice The chain id of Gnosis.\\n uint64 private constant GNOSIS_CHAIN_ID = 100;\\n\\n /// @notice The contract address of the xdai bridge on the source chain.\\n IXDaiBridge private immutable xDaiBridge;\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _xDaiBridge The contract address of the xdai bridge on the source chain.\\n constructor(IXDaiBridge _xDaiBridge) {\\n xDaiBridge = _xDaiBridge;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via XDaiBridge\\n /// @param _bridgeData the core information needed for bridging\\n function startBridgeTokensViaXDaiBridge(\\n ILiFi.BridgeData memory _bridgeData\\n )\\n external\\n nonReentrant\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n onlyAllowDestinationChain(_bridgeData, GNOSIS_CHAIN_ID)\\n onlyAllowSourceToken(_bridgeData, DAI)\\n {\\n LibAsset.depositAsset(DAI, _bridgeData.minAmount);\\n _startBridge(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging via XDaiBridge\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an object containing swap related data to perform swaps before bridging\\n function swapAndStartBridgeTokensViaXDaiBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n onlyAllowDestinationChain(_bridgeData, GNOSIS_CHAIN_ID)\\n onlyAllowSourceToken(_bridgeData, DAI)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n\\n _startBridge(_bridgeData);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via XDaiBridge\\n /// @param _bridgeData the core information needed for bridging\\n function _startBridge(ILiFi.BridgeData memory _bridgeData) private {\\n LibAsset.maxApproveERC20(\\n IERC20(DAI),\\n address(xDaiBridge),\\n _bridgeData.minAmount\\n );\\n xDaiBridge.relayTokens(_bridgeData.receiver, _bridgeData.minAmount);\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IXDaiBridge.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IXDaiBridge {\\n /// @notice Bridge Dai to xDai and sends to receiver\\n /// @dev It's implemented in xDaiBridge on only Ethereum\\n /// @param receiver Receiver address\\n /// @param amount Dai amount\\n function relayTokens(address receiver, uint256 amount) external;\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IXDaiBridge\",\"name\":\"_xDaiBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDestinationChain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSendingToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaXDaiBridge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"}],\"name\":\"swapAndStartBridgeTokensViaXDaiBridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "GnosisBridgeFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000004aa42145aa6ebf72e164c9bbc74fbd3788045016", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/GnosisBridgeFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IXDaiBridge } from \"../Interfaces/IXDaiBridge.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { InvalidSendingToken, NoSwapDataProvided } from \"../Errors/GenericErrors.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title Gnosis Bridge Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through XDaiBridge\n/// @custom:version 1.0.0\ncontract GnosisBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n /// @notice The DAI address on the source chain.\n address private constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n\n /// @notice The chain id of Gnosis.\n uint64 private constant GNOSIS_CHAIN_ID = 100;\n\n /// @notice The contract address of the xdai bridge on the source chain.\n IXDaiBridge private immutable xDaiBridge;\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _xDaiBridge The contract address of the xdai bridge on the source chain.\n constructor(IXDaiBridge _xDaiBridge) {\n xDaiBridge = _xDaiBridge;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via XDaiBridge\n /// @param _bridgeData the core information needed for bridging\n function startBridgeTokensViaXDaiBridge(\n ILiFi.BridgeData memory _bridgeData\n )\n external\n nonReentrant\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n onlyAllowDestinationChain(_bridgeData, GNOSIS_CHAIN_ID)\n onlyAllowSourceToken(_bridgeData, DAI)\n {\n LibAsset.depositAsset(DAI, _bridgeData.minAmount);\n _startBridge(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging via XDaiBridge\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an object containing swap related data to perform swaps before bridging\n function swapAndStartBridgeTokensViaXDaiBridge(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n onlyAllowDestinationChain(_bridgeData, GNOSIS_CHAIN_ID)\n onlyAllowSourceToken(_bridgeData, DAI)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n\n _startBridge(_bridgeData);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via XDaiBridge\n /// @param _bridgeData the core information needed for bridging\n function _startBridge(ILiFi.BridgeData memory _bridgeData) private {\n LibAsset.maxApproveERC20(\n IERC20(DAI),\n address(xDaiBridge),\n _bridgeData.minAmount\n );\n xDaiBridge.relayTokens(_bridgeData.receiver, _bridgeData.minAmount);\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IXDaiBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IXDaiBridge {\n /// @notice Bridge Dai to xDai and sends to receiver\n /// @dev It's implemented in xDaiBridge on only Ethereum\n /// @param receiver Receiver address\n /// @param amount Dai amount\n function relayTokens(address receiver, uint256 amount) external;\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ArbitrumBridgeFacet +0x090e074bc934c4d8b84e168cb6597e87da0c019b +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/ArbitrumBridgeFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IGatewayRouter } from \\\"../Interfaces/IGatewayRouter.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { InvalidAmount } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title Arbitrum Bridge Facet\\n/// @author Li.Finance (https://li.finance)\\n/// @notice Provides functionality for bridging through Arbitrum Bridge\\n/// @custom:version 1.0.0\\ncontract ArbitrumBridgeFacet is\\n ILiFi,\\n ReentrancyGuard,\\n SwapperV2,\\n Validatable\\n{\\n /// Storage ///\\n\\n /// @notice The contract address of the gateway router on the source chain.\\n IGatewayRouter private immutable gatewayRouter;\\n\\n /// @notice The contract address of the inbox on the source chain.\\n IGatewayRouter private immutable inbox;\\n\\n /// Types ///\\n\\n /// @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee.\\n /// @param maxGas Max gas deducted from user's L2 balance to cover L2 execution.\\n /// @param maxGasPrice price bid for L2 execution.\\n struct ArbitrumData {\\n uint256 maxSubmissionCost;\\n uint256 maxGas;\\n uint256 maxGasPrice;\\n }\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _gatewayRouter The contract address of the gateway router on the source chain.\\n /// @param _inbox The contract address of the inbox on the source chain.\\n constructor(IGatewayRouter _gatewayRouter, IGatewayRouter _inbox) {\\n gatewayRouter = _gatewayRouter;\\n inbox = _inbox;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Arbitrum Bridge\\n /// @param _bridgeData Data containing core information for bridging\\n /// @param _arbitrumData Data for gateway router address, asset id and amount\\n function startBridgeTokensViaArbitrumBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n ArbitrumData calldata _arbitrumData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n uint256 cost = _arbitrumData.maxSubmissionCost +\\n _arbitrumData.maxGas *\\n _arbitrumData.maxGasPrice;\\n\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n\\n _startBridge(_bridgeData, _arbitrumData, cost);\\n }\\n\\n /// @notice Performs a swap before bridging via Arbitrum Bridge\\n /// @param _bridgeData Data containing core information for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _arbitrumData Data for gateway router address, asset id and amount\\n function swapAndStartBridgeTokensViaArbitrumBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n ArbitrumData calldata _arbitrumData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n uint256 cost = _arbitrumData.maxSubmissionCost +\\n _arbitrumData.maxGas *\\n _arbitrumData.maxGasPrice;\\n\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n cost\\n );\\n\\n _startBridge(_bridgeData, _arbitrumData, cost);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Arbitrum Bridge\\n /// @param _bridgeData Data containing core information for bridging\\n /// @param _arbitrumData Data for gateway router address, asset id and amount\\n /// @param _cost Additional amount of native asset for the fee\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n ArbitrumData calldata _arbitrumData,\\n uint256 _cost\\n ) private {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n inbox.unsafeCreateRetryableTicket{\\n value: _bridgeData.minAmount + _cost\\n }(\\n _bridgeData.receiver,\\n _bridgeData.minAmount, // l2CallValue\\n _arbitrumData.maxSubmissionCost,\\n _bridgeData.receiver, // excessFeeRefundAddress\\n _bridgeData.receiver, // callValueRefundAddress\\n _arbitrumData.maxGas,\\n _arbitrumData.maxGasPrice,\\n \\\"\\\"\\n );\\n } else {\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n gatewayRouter.getGateway(_bridgeData.sendingAssetId),\\n _bridgeData.minAmount\\n );\\n gatewayRouter.outboundTransfer{ value: _cost }(\\n _bridgeData.sendingAssetId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _arbitrumData.maxGas,\\n _arbitrumData.maxGasPrice,\\n abi.encode(_arbitrumData.maxSubmissionCost, \\\"\\\")\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IGatewayRouter.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.17;\\n\\ninterface IGatewayRouter {\\n /// @notice Transfer non-native assets\\n /// @param _token 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 /// @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 function outboundTransfer(\\n address _token,\\n address _to,\\n uint256 _amount,\\n uint256 _maxGas,\\n uint256 _gasPriceBid,\\n bytes calldata _data\\n ) external payable returns (bytes memory);\\n\\n /// @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress). createRetryableTicket method is the recommended standard.\\n /// @param _destAddr 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 maxgas x gasprice - 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 _maxGas Max gas deducted from user's L2 balance to cover L2 execution\\n /// @param _gasPriceBid price bid for L2 execution\\n /// @param _data ABI encoded data of L2 message\\n /// @return unique id for retryable transaction (keccak256(requestID, uint(0) )\\n function unsafeCreateRetryableTicket(\\n address _destAddr,\\n uint256 _l2CallValue,\\n uint256 _maxSubmissionCost,\\n address _excessFeeRefundAddress,\\n address _callValueRefundAddress,\\n uint256 _maxGas,\\n uint256 _gasPriceBid,\\n bytes calldata _data\\n ) external payable returns (uint256);\\n\\n /// @notice Returns receiving token address on L2\\n /// @param _token Sending token address on L1\\n /// @return Receiving token address on L2\\n function calculateL2TokenAddress(\\n address _token\\n ) external view returns (address);\\n\\n /// @notice Returns exact gateway router address for token\\n /// @param _token Sending token address on L1\\n /// @return Gateway router address for sending token\\n function getGateway(address _token) external view returns (address);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IGatewayRouter\",\"name\":\"_gatewayRouter\",\"type\":\"address\"},{\"internalType\":\"contract IGatewayRouter\",\"name\":\"_inbox\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"maxSubmissionCost\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxGasPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct ArbitrumBridgeFacet.ArbitrumData\",\"name\":\"_arbitrumData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaArbitrumBridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"maxSubmissionCost\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxGasPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct ArbitrumBridgeFacet.ArbitrumData\",\"name\":\"_arbitrumData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaArbitrumBridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "ArbitrumBridgeFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "00000000000000000000000072ce9c846789fdb6fc1f34ac4ad25dd9ef7031ef0000000000000000000000004dbd4fc535ac27206064b68ffcf827b0a60bab3f", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/ArbitrumBridgeFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IGatewayRouter } from \"../Interfaces/IGatewayRouter.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { InvalidAmount } from \"../Errors/GenericErrors.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title Arbitrum Bridge Facet\n/// @author Li.Finance (https://li.finance)\n/// @notice Provides functionality for bridging through Arbitrum Bridge\n/// @custom:version 1.0.0\ncontract ArbitrumBridgeFacet is\n ILiFi,\n ReentrancyGuard,\n SwapperV2,\n Validatable\n{\n /// Storage ///\n\n /// @notice The contract address of the gateway router on the source chain.\n IGatewayRouter private immutable gatewayRouter;\n\n /// @notice The contract address of the inbox on the source chain.\n IGatewayRouter private immutable inbox;\n\n /// Types ///\n\n /// @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee.\n /// @param maxGas Max gas deducted from user's L2 balance to cover L2 execution.\n /// @param maxGasPrice price bid for L2 execution.\n struct ArbitrumData {\n uint256 maxSubmissionCost;\n uint256 maxGas;\n uint256 maxGasPrice;\n }\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _gatewayRouter The contract address of the gateway router on the source chain.\n /// @param _inbox The contract address of the inbox on the source chain.\n constructor(IGatewayRouter _gatewayRouter, IGatewayRouter _inbox) {\n gatewayRouter = _gatewayRouter;\n inbox = _inbox;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Arbitrum Bridge\n /// @param _bridgeData Data containing core information for bridging\n /// @param _arbitrumData Data for gateway router address, asset id and amount\n function startBridgeTokensViaArbitrumBridge(\n ILiFi.BridgeData memory _bridgeData,\n ArbitrumData calldata _arbitrumData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n uint256 cost = _arbitrumData.maxSubmissionCost +\n _arbitrumData.maxGas *\n _arbitrumData.maxGasPrice;\n\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n\n _startBridge(_bridgeData, _arbitrumData, cost);\n }\n\n /// @notice Performs a swap before bridging via Arbitrum Bridge\n /// @param _bridgeData Data containing core information for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _arbitrumData Data for gateway router address, asset id and amount\n function swapAndStartBridgeTokensViaArbitrumBridge(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n ArbitrumData calldata _arbitrumData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n uint256 cost = _arbitrumData.maxSubmissionCost +\n _arbitrumData.maxGas *\n _arbitrumData.maxGasPrice;\n\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n cost\n );\n\n _startBridge(_bridgeData, _arbitrumData, cost);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via Arbitrum Bridge\n /// @param _bridgeData Data containing core information for bridging\n /// @param _arbitrumData Data for gateway router address, asset id and amount\n /// @param _cost Additional amount of native asset for the fee\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n ArbitrumData calldata _arbitrumData,\n uint256 _cost\n ) private {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n inbox.unsafeCreateRetryableTicket{\n value: _bridgeData.minAmount + _cost\n }(\n _bridgeData.receiver,\n _bridgeData.minAmount, // l2CallValue\n _arbitrumData.maxSubmissionCost,\n _bridgeData.receiver, // excessFeeRefundAddress\n _bridgeData.receiver, // callValueRefundAddress\n _arbitrumData.maxGas,\n _arbitrumData.maxGasPrice,\n \"\"\n );\n } else {\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n gatewayRouter.getGateway(_bridgeData.sendingAssetId),\n _bridgeData.minAmount\n );\n gatewayRouter.outboundTransfer{ value: _cost }(\n _bridgeData.sendingAssetId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _arbitrumData.maxGas,\n _arbitrumData.maxGasPrice,\n abi.encode(_arbitrumData.maxSubmissionCost, \"\")\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IGatewayRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\ninterface IGatewayRouter {\n /// @notice Transfer non-native assets\n /// @param _token 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 /// @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 function outboundTransfer(\n address _token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory);\n\n /// @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress). createRetryableTicket method is the recommended standard.\n /// @param _destAddr 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 maxgas x gasprice - 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 _maxGas Max gas deducted from user's L2 balance to cover L2 execution\n /// @param _gasPriceBid price bid for L2 execution\n /// @param _data ABI encoded data of L2 message\n /// @return unique id for retryable transaction (keccak256(requestID, uint(0) )\n function unsafeCreateRetryableTicket(\n address _destAddr,\n uint256 _l2CallValue,\n uint256 _maxSubmissionCost,\n address _excessFeeRefundAddress,\n address _callValueRefundAddress,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (uint256);\n\n /// @notice Returns receiving token address on L2\n /// @param _token Sending token address on L1\n /// @return Receiving token address on L2\n function calculateL2TokenAddress(\n address _token\n ) external view returns (address);\n\n /// @notice Returns exact gateway router address for token\n /// @param _token Sending token address on L1\n /// @return Gateway router address for sending token\n function getGateway(address _token) external view returns (address);\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... -HyphenFacet +0xf2c63815ebd0c4e048ef216c77e2c80aa4ecd59c +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/HyphenFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IHyphenRouter } from \\\"../Interfaces/IHyphenRouter.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title Hyphen Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Hyphen\\n/// @custom:version 1.0.0\\ncontract HyphenFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n /// @notice The contract address of the router on the source chain.\\n IHyphenRouter private immutable router;\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _router The contract address of the router on the source chain.\\n constructor(IHyphenRouter _router) {\\n router = _router;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Hyphen\\n /// @param _bridgeData the core information needed for bridging\\n function startBridgeTokensViaHyphen(\\n ILiFi.BridgeData memory _bridgeData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging via Hyphen\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n function swapAndStartBridgeTokensViaHyphen(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n _startBridge(_bridgeData);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Hyphen\\n /// @param _bridgeData the core information needed for bridging\\n function _startBridge(ILiFi.BridgeData memory _bridgeData) private {\\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // Give the Hyphen router approval to bridge tokens\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(router),\\n _bridgeData.minAmount\\n );\\n\\n router.depositErc20(\\n _bridgeData.destinationChainId,\\n _bridgeData.sendingAssetId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n \\\"LIFI\\\"\\n );\\n } else {\\n router.depositNative{ value: _bridgeData.minAmount }(\\n _bridgeData.receiver,\\n _bridgeData.destinationChainId,\\n \\\"LIFI\\\"\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IHyphenRouter.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\n// https://github.com/bcnmy/hyphen-contract/blob/master/contracts/hyphen/LiquidityPool.sol\\ninterface IHyphenRouter {\\n function depositErc20(\\n uint256 toChainId,\\n address tokenAddress,\\n address receiver,\\n uint256 amount,\\n string calldata tag\\n ) external;\\n\\n function depositNative(\\n address receiver,\\n uint256 toChainId,\\n string calldata tag\\n ) external payable;\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IHyphenRouter\",\"name\":\"_router\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaHyphen\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"}],\"name\":\"swapAndStartBridgeTokensViaHyphen\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "HyphenFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000002a5c2568b10a0e826bfa892cf21ba7218310180b", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/HyphenFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IHyphenRouter } from \"../Interfaces/IHyphenRouter.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title Hyphen Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Hyphen\n/// @custom:version 1.0.0\ncontract HyphenFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n /// @notice The contract address of the router on the source chain.\n IHyphenRouter private immutable router;\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _router The contract address of the router on the source chain.\n constructor(IHyphenRouter _router) {\n router = _router;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Hyphen\n /// @param _bridgeData the core information needed for bridging\n function startBridgeTokensViaHyphen(\n ILiFi.BridgeData memory _bridgeData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging via Hyphen\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n function swapAndStartBridgeTokensViaHyphen(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n _startBridge(_bridgeData);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via Hyphen\n /// @param _bridgeData the core information needed for bridging\n function _startBridge(ILiFi.BridgeData memory _bridgeData) private {\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // Give the Hyphen router approval to bridge tokens\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(router),\n _bridgeData.minAmount\n );\n\n router.depositErc20(\n _bridgeData.destinationChainId,\n _bridgeData.sendingAssetId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n \"LIFI\"\n );\n } else {\n router.depositNative{ value: _bridgeData.minAmount }(\n _bridgeData.receiver,\n _bridgeData.destinationChainId,\n \"LIFI\"\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IHyphenRouter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\n// https://github.com/bcnmy/hyphen-contract/blob/master/contracts/hyphen/LiquidityPool.sol\ninterface IHyphenRouter {\n function depositErc20(\n uint256 toChainId,\n address tokenAddress,\n address receiver,\n uint256 amount,\n string calldata tag\n ) external;\n\n function depositNative(\n address receiver,\n uint256 toChainId,\n string calldata tag\n ) external payable;\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... |MultichainFacet +0x02063a0d7a222c16d5b63213262596b83b07150c +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/MultichainFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { IMultichainRouter } from \\\"../Interfaces/IMultichainRouter.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { InvalidConfig, AlreadyInitialized, NotInitialized } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\ninterface IMultichainERC20 {\\n function Swapout(uint256 amount, address bindaddr) external returns (bool);\\n}\\n\\n/// @title Multichain Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Multichain (Prev. AnySwap)\\n/// @custom:version 1.0.1\\ncontract MultichainFacet is ILiFi, SwapperV2, ReentrancyGuard, Validatable {\\n /// Storage ///\\n\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.facets.multichain\\\");\\n\\n /// Types ///\\n\\n struct Storage {\\n mapping(address => bool) allowedRouters;\\n bool initialized; // no longer used but kept here to maintain the same storage layout\\n address anyNative;\\n mapping(address => address) anyTokenAddresses;\\n }\\n\\n struct MultichainData {\\n address router;\\n }\\n\\n struct AnyMapping {\\n address tokenAddress;\\n address anyTokenAddress;\\n }\\n\\n /// Errors ///\\n\\n error InvalidRouter();\\n\\n /// Events ///\\n\\n event MultichainInitialized();\\n event MultichainRoutersUpdated(address[] routers, bool[] allowed);\\n event AnyMappingUpdated(AnyMapping[] mappings);\\n\\n /// Init ///\\n\\n /// @notice Initialize local variables for the Multichain Facet\\n /// @param anyNative The address of the anyNative (e.g. anyETH) token\\n /// @param routers Allowed Multichain Routers\\n function initMultichain(\\n address anyNative,\\n address[] calldata routers\\n ) external {\\n LibDiamond.enforceIsContractOwner();\\n\\n Storage storage s = getStorage();\\n\\n s.anyNative = anyNative;\\n\\n uint256 len = routers.length;\\n for (uint256 i = 0; i < len; ) {\\n if (routers[i] == address(0)) {\\n revert InvalidConfig();\\n }\\n s.allowedRouters[routers[i]] = true;\\n unchecked {\\n ++i;\\n }\\n }\\n\\n emit MultichainInitialized();\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Updates the tokenAddress > anyTokenAddress storage\\n /// @param mappings A mapping of tokenAddress(es) to anyTokenAddress(es)\\n function updateAddressMappings(AnyMapping[] calldata mappings) external {\\n LibDiamond.enforceIsContractOwner();\\n\\n Storage storage s = getStorage();\\n\\n for (uint64 i; i < mappings.length; ) {\\n s.anyTokenAddresses[mappings[i].tokenAddress] = mappings[i]\\n .anyTokenAddress;\\n unchecked {\\n ++i;\\n }\\n }\\n\\n emit AnyMappingUpdated(mappings);\\n }\\n\\n /// @notice (Batch) register routers\\n /// @param routers Router addresses\\n /// @param allowed Array of whether the addresses are allowed or not\\n function registerRouters(\\n address[] calldata routers,\\n bool[] calldata allowed\\n ) external {\\n LibDiamond.enforceIsContractOwner();\\n\\n Storage storage s = getStorage();\\n\\n uint256 len = routers.length;\\n for (uint256 i = 0; i < len; ) {\\n if (routers[i] == address(0)) {\\n revert InvalidConfig();\\n }\\n s.allowedRouters[routers[i]] = allowed[i];\\n\\n unchecked {\\n ++i;\\n }\\n }\\n emit MultichainRoutersUpdated(routers, allowed);\\n }\\n\\n /// @notice Bridges tokens via Multichain\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _multichainData data specific to Multichain\\n function startBridgeTokensViaMultichain(\\n ILiFi.BridgeData memory _bridgeData,\\n MultichainData calldata _multichainData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n Storage storage s = getStorage();\\n if (!s.allowedRouters[_multichainData.router]) {\\n revert InvalidRouter();\\n }\\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId))\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n\\n _startBridge(_bridgeData, _multichainData);\\n }\\n\\n /// @notice Performs a swap before bridging via Multichain\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _multichainData data specific to Multichain\\n function swapAndStartBridgeTokensViaMultichain(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n MultichainData calldata _multichainData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n Storage storage s = getStorage();\\n\\n if (!s.allowedRouters[_multichainData.router]) {\\n revert InvalidRouter();\\n }\\n\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n _startBridge(_bridgeData, _multichainData);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Multichain\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _multichainData data specific to Multichain\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n MultichainData calldata _multichainData\\n ) private {\\n // check if sendingAsset is a Multichain token that needs to be called directly in order to bridge it\\n if (_multichainData.router == _bridgeData.sendingAssetId) {\\n IMultichainERC20(_bridgeData.sendingAssetId).Swapout(\\n _bridgeData.minAmount,\\n _bridgeData.receiver\\n );\\n } else {\\n Storage storage s = getStorage();\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // call native asset bridge function\\n IMultichainRouter(_multichainData.router).anySwapOutNative{\\n value: _bridgeData.minAmount\\n }(\\n s.anyNative,\\n _bridgeData.receiver,\\n _bridgeData.destinationChainId\\n );\\n } else {\\n // Give Multichain router approval to pull tokens\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n _multichainData.router,\\n _bridgeData.minAmount\\n );\\n\\n address anyToken = s.anyTokenAddresses[\\n _bridgeData.sendingAssetId\\n ];\\n\\n // replace tokenAddress with anyTokenAddress (if mapping found) and call ERC20 asset bridge function\\n IMultichainRouter(_multichainData.router).anySwapOutUnderlying(\\n anyToken != address(0)\\n ? anyToken\\n : _bridgeData.sendingAssetId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _bridgeData.destinationChainId\\n );\\n }\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @dev fetch local storage\\n function getStorage() private pure returns (Storage storage s) {\\n bytes32 namespace = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n s.slot := namespace\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IMultichainRouter.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IMultichainRouter {\\n function anySwapOutUnderlying(\\n address token,\\n address to,\\n uint256 amount,\\n uint256 toChainID\\n ) external;\\n\\n function anySwapOut(\\n address token,\\n address to,\\n uint256 amount,\\n uint256 toChainID\\n ) external;\\n\\n function anySwapOutNative(\\n address token,\\n address to,\\n uint256 toChainID\\n ) external payable;\\n\\n function wNATIVE() external returns (address);\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyContractOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"anyTokenAddress\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct MultichainFacet.AnyMapping[]\",\"name\":\"mappings\",\"type\":\"tuple[]\"}],\"name\":\"AnyMappingUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"MultichainInitialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"routers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"bool[]\",\"name\":\"allowed\",\"type\":\"bool[]\"}],\"name\":\"MultichainRoutersUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"anyNative\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"routers\",\"type\":\"address[]\"}],\"name\":\"initMultichain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"routers\",\"type\":\"address[]\"},{\"internalType\":\"bool[]\",\"name\":\"allowed\",\"type\":\"bool[]\"}],\"name\":\"registerRouters\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"struct MultichainFacet.MultichainData\",\"name\":\"_multichainData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaMultichain\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"struct MultichainFacet.MultichainData\",\"name\":\"_multichainData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaMultichain\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"anyTokenAddress\",\"type\":\"address\"}],\"internalType\":\"struct MultichainFacet.AnyMapping[]\",\"name\":\"mappings\",\"type\":\"tuple[]\"}],\"name\":\"updateAddressMappings\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ContractName: "MultichainFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/MultichainFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { IMultichainRouter } from \"../Interfaces/IMultichainRouter.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { InvalidConfig, AlreadyInitialized, NotInitialized } from \"../Errors/GenericErrors.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\ninterface IMultichainERC20 {\n function Swapout(uint256 amount, address bindaddr) external returns (bool);\n}\n\n/// @title Multichain Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Multichain (Prev. AnySwap)\n/// @custom:version 1.0.1\ncontract MultichainFacet is ILiFi, SwapperV2, ReentrancyGuard, Validatable {\n /// Storage ///\n\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.facets.multichain\");\n\n /// Types ///\n\n struct Storage {\n mapping(address => bool) allowedRouters;\n bool initialized; // no longer used but kept here to maintain the same storage layout\n address anyNative;\n mapping(address => address) anyTokenAddresses;\n }\n\n struct MultichainData {\n address router;\n }\n\n struct AnyMapping {\n address tokenAddress;\n address anyTokenAddress;\n }\n\n /// Errors ///\n\n error InvalidRouter();\n\n /// Events ///\n\n event MultichainInitialized();\n event MultichainRoutersUpdated(address[] routers, bool[] allowed);\n event AnyMappingUpdated(AnyMapping[] mappings);\n\n /// Init ///\n\n /// @notice Initialize local variables for the Multichain Facet\n /// @param anyNative The address of the anyNative (e.g. anyETH) token\n /// @param routers Allowed Multichain Routers\n function initMultichain(\n address anyNative,\n address[] calldata routers\n ) external {\n LibDiamond.enforceIsContractOwner();\n\n Storage storage s = getStorage();\n\n s.anyNative = anyNative;\n\n uint256 len = routers.length;\n for (uint256 i = 0; i < len; ) {\n if (routers[i] == address(0)) {\n revert InvalidConfig();\n }\n s.allowedRouters[routers[i]] = true;\n unchecked {\n ++i;\n }\n }\n\n emit MultichainInitialized();\n }\n\n /// External Methods ///\n\n /// @notice Updates the tokenAddress > anyTokenAddress storage\n /// @param mappings A mapping of tokenAddress(es) to anyTokenAddress(es)\n function updateAddressMappings(AnyMapping[] calldata mappings) external {\n LibDiamond.enforceIsContractOwner();\n\n Storage storage s = getStorage();\n\n for (uint64 i; i < mappings.length; ) {\n s.anyTokenAddresses[mappings[i].tokenAddress] = mappings[i]\n .anyTokenAddress;\n unchecked {\n ++i;\n }\n }\n\n emit AnyMappingUpdated(mappings);\n }\n\n /// @notice (Batch) register routers\n /// @param routers Router addresses\n /// @param allowed Array of whether the addresses are allowed or not\n function registerRouters(\n address[] calldata routers,\n bool[] calldata allowed\n ) external {\n LibDiamond.enforceIsContractOwner();\n\n Storage storage s = getStorage();\n\n uint256 len = routers.length;\n for (uint256 i = 0; i < len; ) {\n if (routers[i] == address(0)) {\n revert InvalidConfig();\n }\n s.allowedRouters[routers[i]] = allowed[i];\n\n unchecked {\n ++i;\n }\n }\n emit MultichainRoutersUpdated(routers, allowed);\n }\n\n /// @notice Bridges tokens via Multichain\n /// @param _bridgeData the core information needed for bridging\n /// @param _multichainData data specific to Multichain\n function startBridgeTokensViaMultichain(\n ILiFi.BridgeData memory _bridgeData,\n MultichainData calldata _multichainData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n Storage storage s = getStorage();\n if (!s.allowedRouters[_multichainData.router]) {\n revert InvalidRouter();\n }\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId))\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n\n _startBridge(_bridgeData, _multichainData);\n }\n\n /// @notice Performs a swap before bridging via Multichain\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _multichainData data specific to Multichain\n function swapAndStartBridgeTokensViaMultichain(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n MultichainData calldata _multichainData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n Storage storage s = getStorage();\n\n if (!s.allowedRouters[_multichainData.router]) {\n revert InvalidRouter();\n }\n\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n _startBridge(_bridgeData, _multichainData);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via Multichain\n /// @param _bridgeData the core information needed for bridging\n /// @param _multichainData data specific to Multichain\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n MultichainData calldata _multichainData\n ) private {\n // check if sendingAsset is a Multichain token that needs to be called directly in order to bridge it\n if (_multichainData.router == _bridgeData.sendingAssetId) {\n IMultichainERC20(_bridgeData.sendingAssetId).Swapout(\n _bridgeData.minAmount,\n _bridgeData.receiver\n );\n } else {\n Storage storage s = getStorage();\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // call native asset bridge function\n IMultichainRouter(_multichainData.router).anySwapOutNative{\n value: _bridgeData.minAmount\n }(\n s.anyNative,\n _bridgeData.receiver,\n _bridgeData.destinationChainId\n );\n } else {\n // Give Multichain router approval to pull tokens\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n _multichainData.router,\n _bridgeData.minAmount\n );\n\n address anyToken = s.anyTokenAddresses[\n _bridgeData.sendingAssetId\n ];\n\n // replace tokenAddress with anyTokenAddress (if mapping found) and call ERC20 asset bridge function\n IMultichainRouter(_multichainData.router).anySwapOutUnderlying(\n anyToken != address(0)\n ? anyToken\n : _bridgeData.sendingAssetId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _bridgeData.destinationChainId\n );\n }\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @dev fetch local storage\n function getStorage() private pure returns (Storage storage s) {\n bytes32 namespace = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n s.slot := namespace\n }\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Interfaces/IMultichainRouter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IMultichainRouter {\n function anySwapOutUnderlying(\n address token,\n address to,\n uint256 amount,\n uint256 toChainID\n ) external;\n\n function anySwapOut(\n address token,\n address to,\n uint256 amount,\n uint256 toChainID\n ) external;\n\n function anySwapOutNative(\n address token,\n address to,\n uint256 toChainID\n ) external payable;\n\n function wNATIVE() external returns (address);\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.1 + Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \AcrossFacet +0xbee13d99dd633feaa2a0935f00cbc859f8305fa7 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/AcrossFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IAcrossSpokePool } from \\\"../Interfaces/IAcrossSpokePool.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2 } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title Across Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Across Protocol\\n/// @custom:version 2.0.0\\ncontract AcrossFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n /// @notice The contract address of the spoke pool on the source chain.\\n IAcrossSpokePool private immutable spokePool;\\n\\n /// @notice The WETH address on the current chain.\\n address private immutable wrappedNative;\\n\\n /// Types ///\\n\\n /// @param relayerFeePct The relayer fee in token percentage with 18 decimals.\\n /// @param quoteTimestamp The timestamp associated with the suggested fee.\\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\\n /// @param maxCount Used to protect the depositor from frontrunning to guarantee their quote remains valid.\\n struct AcrossData {\\n int64 relayerFeePct;\\n uint32 quoteTimestamp;\\n bytes message;\\n uint256 maxCount;\\n }\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _spokePool The contract address of the spoke pool on the source chain.\\n /// @param _wrappedNative The address of the wrapped native token on the source chain.\\n constructor(IAcrossSpokePool _spokePool, address _wrappedNative) {\\n spokePool = _spokePool;\\n wrappedNative = _wrappedNative;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Across\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _acrossData data specific to Across\\n function startBridgeTokensViaAcross(\\n ILiFi.BridgeData memory _bridgeData,\\n AcrossData calldata _acrossData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n validateBridgeData(_bridgeData)\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData, _acrossData);\\n }\\n\\n /// @notice Performs a swap before bridging via Across\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _acrossData data specific to Across\\n function swapAndStartBridgeTokensViaAcross(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n AcrossData calldata _acrossData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n _startBridge(_bridgeData, _acrossData);\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Across\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _acrossData data specific to Across\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n AcrossData calldata _acrossData\\n ) internal {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n spokePool.deposit{ value: _bridgeData.minAmount }(\\n _bridgeData.receiver,\\n wrappedNative,\\n _bridgeData.minAmount,\\n _bridgeData.destinationChainId,\\n _acrossData.relayerFeePct,\\n _acrossData.quoteTimestamp,\\n _acrossData.message,\\n _acrossData.maxCount\\n );\\n } else {\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(spokePool),\\n _bridgeData.minAmount\\n );\\n spokePool.deposit(\\n _bridgeData.receiver,\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n _bridgeData.destinationChainId,\\n _acrossData.relayerFeePct,\\n _acrossData.quoteTimestamp,\\n _acrossData.message,\\n _acrossData.maxCount\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IAcrossSpokePool.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IAcrossSpokePool {\\n function deposit(\\n address recipient, // Recipient address\\n address originToken, // Address of the token\\n uint256 amount, // Token amount\\n uint256 destinationChainId, // ⛓ id\\n int64 relayerFeePct, // see #Fees Calculation\\n uint32 quoteTimestamp, // Timestamp for the quote creation\\n bytes memory message, // Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\\n uint256 maxCount // Used to protect the depositor from frontrunning to guarantee their quote remains valid.\\n ) external payable;\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IAcrossSpokePool\",\"name\":\"_spokePool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_wrappedNative\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"relayerFeePct\",\"type\":\"int64\"},{\"internalType\":\"uint32\",\"name\":\"quoteTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"internalType\":\"struct AcrossFacet.AcrossData\",\"name\":\"_acrossData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaAcross\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"int64\",\"name\":\"relayerFeePct\",\"type\":\"int64\"},{\"internalType\":\"uint32\",\"name\":\"quoteTimestamp\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"internalType\":\"struct AcrossFacet.AcrossData\",\"name\":\"_acrossData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaAcross\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "AcrossFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000005c7bcd6e7de5423a257d81b442095a1a6ced35c5000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/AcrossFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IAcrossSpokePool } from \"../Interfaces/IAcrossSpokePool.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2 } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title Across Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Across Protocol\n/// @custom:version 2.0.0\ncontract AcrossFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n /// @notice The contract address of the spoke pool on the source chain.\n IAcrossSpokePool private immutable spokePool;\n\n /// @notice The WETH address on the current chain.\n address private immutable wrappedNative;\n\n /// Types ///\n\n /// @param relayerFeePct The relayer fee in token percentage with 18 decimals.\n /// @param quoteTimestamp The timestamp associated with the suggested fee.\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\n /// @param maxCount Used to protect the depositor from frontrunning to guarantee their quote remains valid.\n struct AcrossData {\n int64 relayerFeePct;\n uint32 quoteTimestamp;\n bytes message;\n uint256 maxCount;\n }\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _spokePool The contract address of the spoke pool on the source chain.\n /// @param _wrappedNative The address of the wrapped native token on the source chain.\n constructor(IAcrossSpokePool _spokePool, address _wrappedNative) {\n spokePool = _spokePool;\n wrappedNative = _wrappedNative;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Across\n /// @param _bridgeData the core information needed for bridging\n /// @param _acrossData data specific to Across\n function startBridgeTokensViaAcross(\n ILiFi.BridgeData memory _bridgeData,\n AcrossData calldata _acrossData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n validateBridgeData(_bridgeData)\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData, _acrossData);\n }\n\n /// @notice Performs a swap before bridging via Across\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _acrossData data specific to Across\n function swapAndStartBridgeTokensViaAcross(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n AcrossData calldata _acrossData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n _startBridge(_bridgeData, _acrossData);\n }\n\n /// Internal Methods ///\n\n /// @dev Contains the business logic for the bridge via Across\n /// @param _bridgeData the core information needed for bridging\n /// @param _acrossData data specific to Across\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n AcrossData calldata _acrossData\n ) internal {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n spokePool.deposit{ value: _bridgeData.minAmount }(\n _bridgeData.receiver,\n wrappedNative,\n _bridgeData.minAmount,\n _bridgeData.destinationChainId,\n _acrossData.relayerFeePct,\n _acrossData.quoteTimestamp,\n _acrossData.message,\n _acrossData.maxCount\n );\n } else {\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(spokePool),\n _bridgeData.minAmount\n );\n spokePool.deposit(\n _bridgeData.receiver,\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n _bridgeData.destinationChainId,\n _acrossData.relayerFeePct,\n _acrossData.quoteTimestamp,\n _acrossData.message,\n _acrossData.maxCount\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IAcrossSpokePool.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IAcrossSpokePool {\n function deposit(\n address recipient, // Recipient address\n address originToken, // Address of the token\n uint256 amount, // Token amount\n uint256 destinationChainId, // ⛓ id\n int64 relayerFeePct, // see #Fees Calculation\n uint32 quoteTimestamp, // Timestamp for the quote creation\n bytes memory message, // Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\n uint256 maxCount // Used to protect the depositor from frontrunning to guarantee their quote remains valid.\n ) external payable;\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +2.0.0 + Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... -OmniBridgeFacet +0x3c826d17b47db69e1a9c1e32e10768d3709f1b9a +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/OmniBridgeFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IOmniBridge } from \\\"../Interfaces/IOmniBridge.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title OmniBridge Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through OmniBridge\\n/// @custom:version 1.0.0\\ncontract OmniBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n /// @notice The contract address of the foreign omni bridge on the source chain.\\n IOmniBridge private immutable foreignOmniBridge;\\n\\n /// @notice The contract address of the weth omni bridge on the source chain.\\n IOmniBridge private immutable wethOmniBridge;\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _foreignOmniBridge The contract address of the foreign omni bridge on the source chain.\\n /// @param _wethOmniBridge The contract address of the weth omni bridge on the source chain.\\n constructor(IOmniBridge _foreignOmniBridge, IOmniBridge _wethOmniBridge) {\\n foreignOmniBridge = _foreignOmniBridge;\\n wethOmniBridge = _wethOmniBridge;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via OmniBridge\\n /// @param _bridgeData Data contaning core information for bridging\\n function startBridgeTokensViaOmniBridge(\\n ILiFi.BridgeData memory _bridgeData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging via OmniBridge\\n /// @param _bridgeData Data contaning core information for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n function swapAndStartBridgeTokensViaOmniBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n _startBridge(_bridgeData);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via OmniBridge\\n /// @param _bridgeData Data contaning core information for bridging\\n function _startBridge(ILiFi.BridgeData memory _bridgeData) private {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n wethOmniBridge.wrapAndRelayTokens{ value: _bridgeData.minAmount }(\\n _bridgeData.receiver\\n );\\n } else {\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(foreignOmniBridge),\\n _bridgeData.minAmount\\n );\\n foreignOmniBridge.relayTokens(\\n _bridgeData.sendingAssetId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IOmniBridge.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IOmniBridge {\\n /// @dev Initiate the bridge operation for some amount of tokens from msg.sender.\\n /// @param token bridged token contract address.\\n /// @param receiver Receiver address\\n /// @param amount Dai amount\\n function relayTokens(\\n address token,\\n address receiver,\\n uint256 amount\\n ) external;\\n\\n /// @dev Wraps native assets and relays wrapped ERC20 tokens to the other chain.\\n /// @param receiver Bridged assets receiver on the other side of the bridge.\\n function wrapAndRelayTokens(address receiver) external payable;\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IOmniBridge\",\"name\":\"_foreignOmniBridge\",\"type\":\"address\"},{\"internalType\":\"contract IOmniBridge\",\"name\":\"_wethOmniBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaOmniBridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"}],\"name\":\"swapAndStartBridgeTokensViaOmniBridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "OmniBridgeFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "00000000000000000000000088ad09518695c6c3712ac10a214be5109a655671000000000000000000000000a6439ca0fcba1d0f80df0be6a17220fed9c9038a", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/OmniBridgeFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IOmniBridge } from \"../Interfaces/IOmniBridge.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title OmniBridge Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through OmniBridge\n/// @custom:version 1.0.0\ncontract OmniBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n /// @notice The contract address of the foreign omni bridge on the source chain.\n IOmniBridge private immutable foreignOmniBridge;\n\n /// @notice The contract address of the weth omni bridge on the source chain.\n IOmniBridge private immutable wethOmniBridge;\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _foreignOmniBridge The contract address of the foreign omni bridge on the source chain.\n /// @param _wethOmniBridge The contract address of the weth omni bridge on the source chain.\n constructor(IOmniBridge _foreignOmniBridge, IOmniBridge _wethOmniBridge) {\n foreignOmniBridge = _foreignOmniBridge;\n wethOmniBridge = _wethOmniBridge;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via OmniBridge\n /// @param _bridgeData Data contaning core information for bridging\n function startBridgeTokensViaOmniBridge(\n ILiFi.BridgeData memory _bridgeData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging via OmniBridge\n /// @param _bridgeData Data contaning core information for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n function swapAndStartBridgeTokensViaOmniBridge(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n _startBridge(_bridgeData);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via OmniBridge\n /// @param _bridgeData Data contaning core information for bridging\n function _startBridge(ILiFi.BridgeData memory _bridgeData) private {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n wethOmniBridge.wrapAndRelayTokens{ value: _bridgeData.minAmount }(\n _bridgeData.receiver\n );\n } else {\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(foreignOmniBridge),\n _bridgeData.minAmount\n );\n foreignOmniBridge.relayTokens(\n _bridgeData.sendingAssetId,\n _bridgeData.receiver,\n _bridgeData.minAmount\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IOmniBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IOmniBridge {\n /// @dev Initiate the bridge operation for some amount of tokens from msg.sender.\n /// @param token bridged token contract address.\n /// @param receiver Receiver address\n /// @param amount Dai amount\n function relayTokens(\n address token,\n address receiver,\n uint256 amount\n ) external;\n\n /// @dev Wraps native assets and relays wrapped ERC20 tokens to the other chain.\n /// @param receiver Bridged assets receiver on the other side of the bridge.\n function wrapAndRelayTokens(address receiver) external payable;\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... /PolygonBridgeFacet +0xf609fdba8f7a020975a7c82c82f6a1f526f9a8fc +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/PolygonBridgeFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IRootChainManager } from \\\"../Interfaces/IRootChainManager.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title Polygon Bridge Facet\\n/// @author Li.Finance (https://li.finance)\\n/// @notice Provides functionality for bridging through Polygon Bridge\\n/// @custom:version 1.0.0\\ncontract PolygonBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n /// @notice The contract address of the RootChainManager on the source chain.\\n IRootChainManager private immutable rootChainManager;\\n\\n /// @notice The contract address of the ERC20Predicate on the source chain.\\n address private immutable erc20Predicate;\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _rootChainManager The contract address of the RootChainManager on the source chain.\\n /// @param _erc20Predicate The contract address of the ERC20Predicate on the source chain.\\n constructor(IRootChainManager _rootChainManager, address _erc20Predicate) {\\n rootChainManager = _rootChainManager;\\n erc20Predicate = _erc20Predicate;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Polygon Bridge\\n /// @param _bridgeData Data containing core information for bridging\\n function startBridgeTokensViaPolygonBridge(\\n ILiFi.BridgeData memory _bridgeData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging via Polygon Bridge\\n /// @param _bridgeData Data containing core information for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n function swapAndStartBridgeTokensViaPolygonBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n _startBridge(_bridgeData);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Polygon Bridge\\n /// @param _bridgeData Data containing core information for bridging\\n function _startBridge(ILiFi.BridgeData memory _bridgeData) private {\\n address childToken;\\n\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n rootChainManager.depositEtherFor{ value: _bridgeData.minAmount }(\\n _bridgeData.receiver\\n );\\n } else {\\n childToken = rootChainManager.rootToChildToken(\\n _bridgeData.sendingAssetId\\n );\\n\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n erc20Predicate,\\n _bridgeData.minAmount\\n );\\n\\n bytes memory depositData = abi.encode(_bridgeData.minAmount);\\n rootChainManager.depositFor(\\n _bridgeData.receiver,\\n _bridgeData.sendingAssetId,\\n depositData\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IRootChainManager.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.17;\\n\\ninterface IRootChainManager {\\n /// @notice Move ether from root to child chain, accepts ether transfer\\n /// @dev Keep in mind this ether cannot be used to pay gas on child chain\\n /// Use Matic tokens deposited using plasma mechanism for that\\n /// @param user address of account that should receive WETH on child chain\\n function depositEtherFor(address user) external payable;\\n\\n /// @notice Move tokens from root to child chain\\n /// @dev This mechanism supports arbitrary tokens as long as\\n /// its predicate has been registered and the token is mapped\\n /// @param user address of account that should receive this deposit on child chain\\n /// @param rootToken address of token that is being deposited\\n /// @param depositData bytes data that is sent to predicate and\\n /// child token contracts to handle deposit\\n function depositFor(\\n address user,\\n address rootToken,\\n bytes calldata depositData\\n ) external;\\n\\n /// @notice Returns child token address for root token\\n /// @param rootToken Root token address\\n /// @return childToken Child token address\\n function rootToChildToken(\\n address rootToken\\n ) external view returns (address childToken);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IRootChainManager\",\"name\":\"_rootChainManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_erc20Predicate\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaPolygonBridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"}],\"name\":\"swapAndStartBridgeTokensViaPolygonBridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "PolygonBridgeFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "000000000000000000000000a0c68c638235ee32657e8f720a23cec1bfc77c7700000000000000000000000040ec5b33f54e0e8a33a975908c5ba1c14e5bbbdf", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/PolygonBridgeFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IRootChainManager } from \"../Interfaces/IRootChainManager.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title Polygon Bridge Facet\n/// @author Li.Finance (https://li.finance)\n/// @notice Provides functionality for bridging through Polygon Bridge\n/// @custom:version 1.0.0\ncontract PolygonBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n /// @notice The contract address of the RootChainManager on the source chain.\n IRootChainManager private immutable rootChainManager;\n\n /// @notice The contract address of the ERC20Predicate on the source chain.\n address private immutable erc20Predicate;\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _rootChainManager The contract address of the RootChainManager on the source chain.\n /// @param _erc20Predicate The contract address of the ERC20Predicate on the source chain.\n constructor(IRootChainManager _rootChainManager, address _erc20Predicate) {\n rootChainManager = _rootChainManager;\n erc20Predicate = _erc20Predicate;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Polygon Bridge\n /// @param _bridgeData Data containing core information for bridging\n function startBridgeTokensViaPolygonBridge(\n ILiFi.BridgeData memory _bridgeData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging via Polygon Bridge\n /// @param _bridgeData Data containing core information for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n function swapAndStartBridgeTokensViaPolygonBridge(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n _startBridge(_bridgeData);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via Polygon Bridge\n /// @param _bridgeData Data containing core information for bridging\n function _startBridge(ILiFi.BridgeData memory _bridgeData) private {\n address childToken;\n\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n rootChainManager.depositEtherFor{ value: _bridgeData.minAmount }(\n _bridgeData.receiver\n );\n } else {\n childToken = rootChainManager.rootToChildToken(\n _bridgeData.sendingAssetId\n );\n\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n erc20Predicate,\n _bridgeData.minAmount\n );\n\n bytes memory depositData = abi.encode(_bridgeData.minAmount);\n rootChainManager.depositFor(\n _bridgeData.receiver,\n _bridgeData.sendingAssetId,\n depositData\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IRootChainManager.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\ninterface IRootChainManager {\n /// @notice Move ether from root to child chain, accepts ether transfer\n /// @dev Keep in mind this ether cannot be used to pay gas on child chain\n /// Use Matic tokens deposited using plasma mechanism for that\n /// @param user address of account that should receive WETH on child chain\n function depositEtherFor(address user) external payable;\n\n /// @notice Move tokens from root to child chain\n /// @dev This mechanism supports arbitrary tokens as long as\n /// its predicate has been registered and the token is mapped\n /// @param user address of account that should receive this deposit on child chain\n /// @param rootToken address of token that is being deposited\n /// @param depositData bytes data that is sent to predicate and\n /// child token contracts to handle deposit\n function depositFor(\n address user,\n address rootToken,\n bytes calldata depositData\n ) external;\n\n /// @notice Returns child token address for root token\n /// @param rootToken Root token address\n /// @return childToken Child token address\n function rootToChildToken(\n address rootToken\n ) external view returns (address childToken);\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... -StargateFacet +0x7d1940fdff0b37c137b105ce7967b3b86db42648 +{ + SourceCode: "", + ABI: "Contract source code not verified", + ContractName: "", + CompilerVersion: "", + OptimizationUsed: "", + Runs: "", + ConstructorArguments: "", + EVMVersion: "Default", + Library: "", + LicenseType: "Unknown", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} + +null + Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... |PeripheryRegistryFacet +0x69cb467efd8044ac9edb88f363309ab1cbfa0a15 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/PeripheryRegistryFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\n\\n/// @title Periphery Registry Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice A simple registry to track LIFI periphery contracts\\n/// @custom:version 1.0.0\\ncontract PeripheryRegistryFacet {\\n /// Storage ///\\n\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.facets.periphery_registry\\\");\\n\\n /// Types ///\\n\\n struct Storage {\\n mapping(string => address) contracts;\\n }\\n\\n /// Events ///\\n\\n event PeripheryContractRegistered(string name, address contractAddress);\\n\\n /// External Methods ///\\n\\n /// @notice Registers a periphery contract address with a specified name\\n /// @param _name the name to register the contract address under\\n /// @param _contractAddress the address of the contract to register\\n function registerPeripheryContract(\\n string calldata _name,\\n address _contractAddress\\n ) external {\\n LibDiamond.enforceIsContractOwner();\\n Storage storage s = getStorage();\\n s.contracts[_name] = _contractAddress;\\n emit PeripheryContractRegistered(_name, _contractAddress);\\n }\\n\\n /// @notice Returns the registered contract address by its name\\n /// @param _name the registered name of the contract\\n function getPeripheryContract(\\n string calldata _name\\n ) external view returns (address) {\\n return getStorage().contracts[_name];\\n }\\n\\n /// @dev fetch local storage\\n function getStorage() private pure returns (Storage storage s) {\\n bytes32 namespace = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n s.slot := namespace\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[],\"name\":\"OnlyContractOwner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"}],\"name\":\"PeripheryContractRegistered\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"getPeripheryContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_contractAddress\",\"type\":\"address\"}],\"name\":\"registerPeripheryContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ContractName: "PeripheryRegistryFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/PeripheryRegistryFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\n\n/// @title Periphery Registry Facet\n/// @author LI.FI (https://li.fi)\n/// @notice A simple registry to track LIFI periphery contracts\n/// @custom:version 1.0.0\ncontract PeripheryRegistryFacet {\n /// Storage ///\n\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.facets.periphery_registry\");\n\n /// Types ///\n\n struct Storage {\n mapping(string => address) contracts;\n }\n\n /// Events ///\n\n event PeripheryContractRegistered(string name, address contractAddress);\n\n /// External Methods ///\n\n /// @notice Registers a periphery contract address with a specified name\n /// @param _name the name to register the contract address under\n /// @param _contractAddress the address of the contract to register\n function registerPeripheryContract(\n string calldata _name,\n address _contractAddress\n ) external {\n LibDiamond.enforceIsContractOwner();\n Storage storage s = getStorage();\n s.contracts[_name] = _contractAddress;\n emit PeripheryContractRegistered(_name, _contractAddress);\n }\n\n /// @notice Returns the registered contract address by its name\n /// @param _name the registered name of the contract\n function getPeripheryContract(\n string calldata _name\n ) external view returns (address) {\n return getStorage().contracts[_name];\n }\n\n /// @dev fetch local storage\n function getStorage() private pure returns (Storage storage s) {\n bytes32 namespace = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n s.slot := namespace\n }\n }\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \GenericSwapFacet +0x2b7d2c78bd801cc06ddcf91dee2e8fae22814f7e +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/GenericSwapFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { ContractCallNotAllowed, CumulativeSlippageTooHigh, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ERC20, SafeTransferLib } from \\\"solmate/utils/SafeTransferLib.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\n\\n/// @title GenericSwapFacet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for swapping through any APPROVED DEX\\n/// @dev Can only execute calldata for APPROVED function selectors\\n/// @custom:version 2.0.0\\ncontract GenericSwapFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n // using SafeERC20 for ERC20;\\n using SafeTransferLib for ERC20;\\n\\n /// External Methods ///\\n\\n /// @notice Performs a single swap from an ERC20 token to another ERC20 token\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _integrator the name of the integrator\\n /// @param _referrer the address of the referrer\\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\\n /// @param _minAmountOut the minimum amount of the final asset to receive\\n /// @param _swapData an object containing swap related data to perform swaps before bridging\\n function swapTokensSingleERC20ToERC20(\\n bytes32 _transactionId,\\n string calldata _integrator,\\n string calldata _referrer,\\n address payable _receiver,\\n uint256 _minAmountOut,\\n LibSwap.SwapData calldata _swapData\\n ) external payable {\\n _depositAndSwapERC20(_swapData);\\n\\n address receivingAssetId = _swapData.receivingAssetId;\\n address sendingAssetId = _swapData.sendingAssetId;\\n\\n // get contract's balance (which will be sent in full to user)\\n uint256 amountReceived = ERC20(receivingAssetId).balanceOf(\\n address(this)\\n );\\n\\n // ensure that minAmountOut was received\\n if (amountReceived < _minAmountOut)\\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\\n\\n // transfer funds to receiver\\n ERC20(receivingAssetId).safeTransfer(_receiver, amountReceived);\\n\\n // emit events (both required for tracking)\\n uint256 fromAmount = _swapData.fromAmount;\\n emit LibSwap.AssetSwapped(\\n _transactionId,\\n _swapData.callTo,\\n sendingAssetId,\\n receivingAssetId,\\n fromAmount,\\n amountReceived,\\n block.timestamp\\n );\\n\\n emit LiFiGenericSwapCompleted(\\n _transactionId,\\n _integrator,\\n _referrer,\\n _receiver,\\n sendingAssetId,\\n receivingAssetId,\\n fromAmount,\\n amountReceived\\n );\\n }\\n\\n /// @notice Performs a single swap from an ERC20 token to the network's native token\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _integrator the name of the integrator\\n /// @param _referrer the address of the referrer\\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\\n /// @param _minAmountOut the minimum amount of the final asset to receive\\n /// @param _swapData an object containing swap related data to perform swaps before bridging\\n function swapTokensSingleERC20ToNative(\\n bytes32 _transactionId,\\n string calldata _integrator,\\n string calldata _referrer,\\n address payable _receiver,\\n uint256 _minAmountOut,\\n LibSwap.SwapData calldata _swapData\\n ) external payable {\\n _depositAndSwapERC20(_swapData);\\n\\n // get contract's balance (which will be sent in full to user)\\n uint256 amountReceived = address(this).balance;\\n\\n // ensure that minAmountOut was received\\n if (amountReceived < _minAmountOut)\\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\\n\\n // transfer funds to receiver\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = _receiver.call{ value: amountReceived }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n\\n // emit events (both required for tracking)\\n address receivingAssetId = _swapData.receivingAssetId;\\n address sendingAssetId = _swapData.sendingAssetId;\\n uint256 fromAmount = _swapData.fromAmount;\\n emit LibSwap.AssetSwapped(\\n _transactionId,\\n _swapData.callTo,\\n sendingAssetId,\\n receivingAssetId,\\n fromAmount,\\n amountReceived,\\n block.timestamp\\n );\\n\\n emit LiFiGenericSwapCompleted(\\n _transactionId,\\n _integrator,\\n _referrer,\\n _receiver,\\n sendingAssetId,\\n receivingAssetId,\\n fromAmount,\\n amountReceived\\n );\\n }\\n\\n /// @notice Performs a single swap from the network's native token to ERC20 token\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _integrator the name of the integrator\\n /// @param _referrer the address of the referrer\\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\\n /// @param _minAmountOut the minimum amount of the final asset to receive\\n /// @param _swapData an object containing swap related data to perform swaps before bridging\\n function swapTokensSingleNativeToERC20(\\n bytes32 _transactionId,\\n string calldata _integrator,\\n string calldata _referrer,\\n address payable _receiver,\\n uint256 _minAmountOut,\\n LibSwap.SwapData calldata _swapData\\n ) external payable {\\n address callTo = _swapData.callTo;\\n // ensure that contract (callTo) and function selector are whitelisted\\n if (\\n !(LibAllowList.contractIsAllowed(callTo) &&\\n LibAllowList.selectorIsAllowed(bytes4(_swapData.callData[:4])))\\n ) revert ContractCallNotAllowed();\\n\\n // execute swap\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = callTo.call{ value: msg.value }(\\n _swapData.callData\\n );\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n // get contract's balance (which will be sent in full to user)\\n address receivingAssetId = _swapData.receivingAssetId;\\n uint256 amountReceived = ERC20(receivingAssetId).balanceOf(\\n address(this)\\n );\\n\\n // ensure that minAmountOut was received\\n if (amountReceived < _minAmountOut)\\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\\n\\n // transfer funds to receiver\\n ERC20(receivingAssetId).safeTransfer(_receiver, amountReceived);\\n\\n // emit events (both required for tracking)\\n address sendingAssetId = _swapData.sendingAssetId;\\n uint256 fromAmount = _swapData.fromAmount;\\n emit LibSwap.AssetSwapped(\\n _transactionId,\\n callTo,\\n sendingAssetId,\\n receivingAssetId,\\n fromAmount,\\n amountReceived,\\n block.timestamp\\n );\\n\\n emit LiFiGenericSwapCompleted(\\n _transactionId,\\n _integrator,\\n _referrer,\\n _receiver,\\n sendingAssetId,\\n receivingAssetId,\\n fromAmount,\\n amountReceived\\n );\\n }\\n\\n /// @notice Performs multiple swaps (of any kind) in one transaction\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _integrator the name of the integrator\\n /// @param _referrer the address of the referrer\\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\\n /// @param _minAmountOut the minimum amount of the final asset to receive\\n /// @param _swapData an object containing swap related data to perform swaps before bridging\\n function swapTokensGeneric(\\n bytes32 _transactionId,\\n string calldata _integrator,\\n string calldata _referrer,\\n address payable _receiver,\\n uint256 _minAmountOut,\\n LibSwap.SwapData[] calldata _swapData\\n ) external payable nonReentrant refundExcessNative(_receiver) {\\n uint256 postSwapBalance = _depositAndSwap(\\n _transactionId,\\n _minAmountOut,\\n _swapData,\\n _receiver\\n );\\n address receivingAssetId = _swapData[_swapData.length - 1]\\n .receivingAssetId;\\n LibAsset.transferAsset(receivingAssetId, _receiver, postSwapBalance);\\n\\n emit LiFiGenericSwapCompleted(\\n _transactionId,\\n _integrator,\\n _referrer,\\n _receiver,\\n _swapData[0].sendingAssetId,\\n receivingAssetId,\\n _swapData[0].fromAmount,\\n postSwapBalance\\n );\\n }\\n\\n /// Internal helper methods ///\\n\\n function _depositAndSwapERC20(\\n LibSwap.SwapData calldata _swapData\\n ) private {\\n ERC20 sendingAsset = ERC20(_swapData.sendingAssetId);\\n uint256 fromAmount = _swapData.fromAmount;\\n // deposit funds\\n sendingAsset.safeTransferFrom(msg.sender, address(this), fromAmount);\\n\\n // ensure that contract (callTo) and function selector are whitelisted\\n address callTo = _swapData.callTo;\\n address approveTo = _swapData.approveTo;\\n if (\\n !(LibAllowList.contractIsAllowed(callTo) &&\\n LibAllowList.selectorIsAllowed(bytes4(_swapData.callData[:4])))\\n ) revert ContractCallNotAllowed();\\n\\n // ensure that approveTo address is also whitelisted if it differs from callTo\\n if (approveTo != callTo && !LibAllowList.contractIsAllowed(approveTo))\\n revert ContractCallNotAllowed();\\n\\n // check if the current allowance is sufficient\\n uint256 currentAllowance = sendingAsset.allowance(\\n address(this),\\n approveTo\\n );\\n\\n // check if existing allowance is sufficient\\n if (currentAllowance < fromAmount) {\\n // check if is non-zero, set to 0 if not\\n if (currentAllowance != 0) sendingAsset.safeApprove(approveTo, 0);\\n // set allowance to uint max to avoid future approvals\\n sendingAsset.safeApprove(approveTo, type(uint256).max);\\n }\\n\\n // execute swap\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = callTo.call(_swapData.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/solmate/src/utils/SafeTransferLib.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\nimport {ERC20} from \\\"../tokens/ERC20.sol\\\";\\n\\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\\nlibrary SafeTransferLib {\\n /*//////////////////////////////////////////////////////////////\\n ETH OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferETH(address to, uint256 amount) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Transfer the ETH and store if it succeeded or not.\\n success := call(gas(), to, amount, 0, 0, 0, 0)\\n }\\n\\n require(success, \\\"ETH_TRANSFER_FAILED\\\");\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferFrom(\\n ERC20 token,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), from) // Append the \\\"from\\\" argument.\\n mstore(add(freeMemoryPointer, 36), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 68), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FROM_FAILED\\\");\\n }\\n\\n function safeTransfer(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FAILED\\\");\\n }\\n\\n function safeApprove(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"APPROVE_FAILED\\\");\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n },\r\n \"lib/solmate/src/tokens/ERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\\nabstract contract ERC20 {\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /*//////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string public name;\\n\\n string public symbol;\\n\\n uint8 public immutable decimals;\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 public totalSupply;\\n\\n mapping(address => uint256) public balanceOf;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 internal immutable INITIAL_CHAIN_ID;\\n\\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\\n\\n mapping(address => uint256) public nonces;\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n constructor(\\n string memory _name,\\n string memory _symbol,\\n uint8 _decimals\\n ) {\\n name = _name;\\n symbol = _symbol;\\n decimals = _decimals;\\n\\n INITIAL_CHAIN_ID = block.chainid;\\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function approve(address spender, uint256 amount) public virtual returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n\\n return true;\\n }\\n\\n function transfer(address to, uint256 amount) public virtual returns (bool) {\\n balanceOf[msg.sender] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(msg.sender, to, amount);\\n\\n return true;\\n }\\n\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual returns (bool) {\\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\\n\\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\\n\\n balanceOf[from] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n return true;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 LOGIC\\n //////////////////////////////////////////////////////////////*/\\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 ) public virtual {\\n require(deadline >= block.timestamp, \\\"PERMIT_DEADLINE_EXPIRED\\\");\\n\\n // Unchecked because the only math done is incrementing\\n // the owner's nonce which cannot realistically overflow.\\n unchecked {\\n address recoveredAddress = ecrecover(\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR(),\\n keccak256(\\n abi.encode(\\n keccak256(\\n \\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\"\\n ),\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n require(recoveredAddress != address(0) && recoveredAddress == owner, \\\"INVALID_SIGNER\\\");\\n\\n allowance[recoveredAddress][spender] = value;\\n }\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\\n }\\n\\n function computeDomainSeparator() internal view virtual returns (bytes32) {\\n return\\n keccak256(\\n abi.encode(\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"),\\n keccak256(bytes(name)),\\n keccak256(\\\"1\\\"),\\n block.chainid,\\n address(this)\\n )\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _mint(address to, uint256 amount) internal virtual {\\n totalSupply += amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(address(0), to, amount);\\n }\\n\\n function _burn(address from, uint256 amount) internal virtual {\\n balanceOf[from] -= amount;\\n\\n // Cannot underflow because a user's balance\\n // will never be larger than the total supply.\\n unchecked {\\n totalSupply -= amount;\\n }\\n\\n emit Transfer(from, address(0), amount);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"_integrator\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_referrer\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minAmountOut\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"}],\"name\":\"swapTokensGeneric\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"_integrator\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_referrer\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minAmountOut\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData\",\"name\":\"_swapData\",\"type\":\"tuple\"}],\"name\":\"swapTokensSingleERC20ToERC20\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"_integrator\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_referrer\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minAmountOut\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData\",\"name\":\"_swapData\",\"type\":\"tuple\"}],\"name\":\"swapTokensSingleERC20ToNative\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"_integrator\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_referrer\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minAmountOut\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData\",\"name\":\"_swapData\",\"type\":\"tuple\"}],\"name\":\"swapTokensSingleNativeToERC20\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "GenericSwapFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/GenericSwapFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { ContractCallNotAllowed, CumulativeSlippageTooHigh, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport { ERC20, SafeTransferLib } from \"solmate/utils/SafeTransferLib.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\n\n/// @title GenericSwapFacet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for swapping through any APPROVED DEX\n/// @dev Can only execute calldata for APPROVED function selectors\n/// @custom:version 2.0.0\ncontract GenericSwapFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n // using SafeERC20 for ERC20;\n using SafeTransferLib for ERC20;\n\n /// External Methods ///\n\n /// @notice Performs a single swap from an ERC20 token to another ERC20 token\n /// @param _transactionId the transaction id associated with the operation\n /// @param _integrator the name of the integrator\n /// @param _referrer the address of the referrer\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\n /// @param _minAmountOut the minimum amount of the final asset to receive\n /// @param _swapData an object containing swap related data to perform swaps before bridging\n function swapTokensSingleERC20ToERC20(\n bytes32 _transactionId,\n string calldata _integrator,\n string calldata _referrer,\n address payable _receiver,\n uint256 _minAmountOut,\n LibSwap.SwapData calldata _swapData\n ) external payable {\n _depositAndSwapERC20(_swapData);\n\n address receivingAssetId = _swapData.receivingAssetId;\n address sendingAssetId = _swapData.sendingAssetId;\n\n // get contract's balance (which will be sent in full to user)\n uint256 amountReceived = ERC20(receivingAssetId).balanceOf(\n address(this)\n );\n\n // ensure that minAmountOut was received\n if (amountReceived < _minAmountOut)\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\n\n // transfer funds to receiver\n ERC20(receivingAssetId).safeTransfer(_receiver, amountReceived);\n\n // emit events (both required for tracking)\n uint256 fromAmount = _swapData.fromAmount;\n emit LibSwap.AssetSwapped(\n _transactionId,\n _swapData.callTo,\n sendingAssetId,\n receivingAssetId,\n fromAmount,\n amountReceived,\n block.timestamp\n );\n\n emit LiFiGenericSwapCompleted(\n _transactionId,\n _integrator,\n _referrer,\n _receiver,\n sendingAssetId,\n receivingAssetId,\n fromAmount,\n amountReceived\n );\n }\n\n /// @notice Performs a single swap from an ERC20 token to the network's native token\n /// @param _transactionId the transaction id associated with the operation\n /// @param _integrator the name of the integrator\n /// @param _referrer the address of the referrer\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\n /// @param _minAmountOut the minimum amount of the final asset to receive\n /// @param _swapData an object containing swap related data to perform swaps before bridging\n function swapTokensSingleERC20ToNative(\n bytes32 _transactionId,\n string calldata _integrator,\n string calldata _referrer,\n address payable _receiver,\n uint256 _minAmountOut,\n LibSwap.SwapData calldata _swapData\n ) external payable {\n _depositAndSwapERC20(_swapData);\n\n // get contract's balance (which will be sent in full to user)\n uint256 amountReceived = address(this).balance;\n\n // ensure that minAmountOut was received\n if (amountReceived < _minAmountOut)\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\n\n // transfer funds to receiver\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = _receiver.call{ value: amountReceived }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n\n // emit events (both required for tracking)\n address receivingAssetId = _swapData.receivingAssetId;\n address sendingAssetId = _swapData.sendingAssetId;\n uint256 fromAmount = _swapData.fromAmount;\n emit LibSwap.AssetSwapped(\n _transactionId,\n _swapData.callTo,\n sendingAssetId,\n receivingAssetId,\n fromAmount,\n amountReceived,\n block.timestamp\n );\n\n emit LiFiGenericSwapCompleted(\n _transactionId,\n _integrator,\n _referrer,\n _receiver,\n sendingAssetId,\n receivingAssetId,\n fromAmount,\n amountReceived\n );\n }\n\n /// @notice Performs a single swap from the network's native token to ERC20 token\n /// @param _transactionId the transaction id associated with the operation\n /// @param _integrator the name of the integrator\n /// @param _referrer the address of the referrer\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\n /// @param _minAmountOut the minimum amount of the final asset to receive\n /// @param _swapData an object containing swap related data to perform swaps before bridging\n function swapTokensSingleNativeToERC20(\n bytes32 _transactionId,\n string calldata _integrator,\n string calldata _referrer,\n address payable _receiver,\n uint256 _minAmountOut,\n LibSwap.SwapData calldata _swapData\n ) external payable {\n address callTo = _swapData.callTo;\n // ensure that contract (callTo) and function selector are whitelisted\n if (\n !(LibAllowList.contractIsAllowed(callTo) &&\n LibAllowList.selectorIsAllowed(bytes4(_swapData.callData[:4])))\n ) revert ContractCallNotAllowed();\n\n // execute swap\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = callTo.call{ value: msg.value }(\n _swapData.callData\n );\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n // get contract's balance (which will be sent in full to user)\n address receivingAssetId = _swapData.receivingAssetId;\n uint256 amountReceived = ERC20(receivingAssetId).balanceOf(\n address(this)\n );\n\n // ensure that minAmountOut was received\n if (amountReceived < _minAmountOut)\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\n\n // transfer funds to receiver\n ERC20(receivingAssetId).safeTransfer(_receiver, amountReceived);\n\n // emit events (both required for tracking)\n address sendingAssetId = _swapData.sendingAssetId;\n uint256 fromAmount = _swapData.fromAmount;\n emit LibSwap.AssetSwapped(\n _transactionId,\n callTo,\n sendingAssetId,\n receivingAssetId,\n fromAmount,\n amountReceived,\n block.timestamp\n );\n\n emit LiFiGenericSwapCompleted(\n _transactionId,\n _integrator,\n _referrer,\n _receiver,\n sendingAssetId,\n receivingAssetId,\n fromAmount,\n amountReceived\n );\n }\n\n /// @notice Performs multiple swaps (of any kind) in one transaction\n /// @param _transactionId the transaction id associated with the operation\n /// @param _integrator the name of the integrator\n /// @param _referrer the address of the referrer\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\n /// @param _minAmountOut the minimum amount of the final asset to receive\n /// @param _swapData an object containing swap related data to perform swaps before bridging\n function swapTokensGeneric(\n bytes32 _transactionId,\n string calldata _integrator,\n string calldata _referrer,\n address payable _receiver,\n uint256 _minAmountOut,\n LibSwap.SwapData[] calldata _swapData\n ) external payable nonReentrant refundExcessNative(_receiver) {\n uint256 postSwapBalance = _depositAndSwap(\n _transactionId,\n _minAmountOut,\n _swapData,\n _receiver\n );\n address receivingAssetId = _swapData[_swapData.length - 1]\n .receivingAssetId;\n LibAsset.transferAsset(receivingAssetId, _receiver, postSwapBalance);\n\n emit LiFiGenericSwapCompleted(\n _transactionId,\n _integrator,\n _referrer,\n _receiver,\n _swapData[0].sendingAssetId,\n receivingAssetId,\n _swapData[0].fromAmount,\n postSwapBalance\n );\n }\n\n /// Internal helper methods ///\n\n function _depositAndSwapERC20(\n LibSwap.SwapData calldata _swapData\n ) private {\n ERC20 sendingAsset = ERC20(_swapData.sendingAssetId);\n uint256 fromAmount = _swapData.fromAmount;\n // deposit funds\n sendingAsset.safeTransferFrom(msg.sender, address(this), fromAmount);\n\n // ensure that contract (callTo) and function selector are whitelisted\n address callTo = _swapData.callTo;\n address approveTo = _swapData.approveTo;\n if (\n !(LibAllowList.contractIsAllowed(callTo) &&\n LibAllowList.selectorIsAllowed(bytes4(_swapData.callData[:4])))\n ) revert ContractCallNotAllowed();\n\n // ensure that approveTo address is also whitelisted if it differs from callTo\n if (approveTo != callTo && !LibAllowList.contractIsAllowed(approveTo))\n revert ContractCallNotAllowed();\n\n // check if the current allowance is sufficient\n uint256 currentAllowance = sendingAsset.allowance(\n address(this),\n approveTo\n );\n\n // check if existing allowance is sufficient\n if (currentAllowance < fromAmount) {\n // check if is non-zero, set to 0 if not\n if (currentAllowance != 0) sendingAsset.safeApprove(approveTo, 0);\n // set allowance to uint max to avoid future approvals\n sendingAsset.safeApprove(approveTo, type(uint256).max);\n }\n\n // execute swap\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = callTo.call(_swapData.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/solmate/src/utils/SafeTransferLib.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20} from \"../tokens/ERC20.sol\";\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n /*//////////////////////////////////////////////////////////////\n ETH OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferETH(address to, uint256 amount) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Transfer the ETH and store if it succeeded or not.\n success := call(gas(), to, amount, 0, 0, 0, 0)\n }\n\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferFrom(\n ERC20 token,\n address from,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), from) // Append the \"from\" argument.\n mstore(add(freeMemoryPointer, 36), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 68), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FROM_FAILED\");\n }\n\n function safeTransfer(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FAILED\");\n }\n\n function safeApprove(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"APPROVE_FAILED\");\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + }, + "lib/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\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 ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +2.0.0 + Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... -HopFacet +0xd84d9a8bf830496c4dec917bc27d22e09e01cb8a +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/HopFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IHopBridge } from \\\"../Interfaces/IHopBridge.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { InvalidConfig, AlreadyInitialized, NotInitialized } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title Hop Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Hop\\n/// @custom:version 2.0.0\\ncontract HopFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n bytes32 internal constant NAMESPACE = keccak256(\\\"com.lifi.facets.hop\\\");\\n\\n /// Types ///\\n\\n struct Storage {\\n mapping(address => IHopBridge) bridges;\\n bool initialized; // no longer used but kept here to maintain the same storage layout\\n }\\n\\n struct Config {\\n address assetId;\\n address bridge;\\n }\\n\\n struct HopData {\\n uint256 bonderFee;\\n uint256 amountOutMin;\\n uint256 deadline;\\n uint256 destinationAmountOutMin;\\n uint256 destinationDeadline;\\n address relayer;\\n uint256 relayerFee;\\n uint256 nativeFee;\\n }\\n\\n /// Events ///\\n\\n event HopInitialized(Config[] configs);\\n event HopBridgeRegistered(address indexed assetId, address bridge);\\n\\n /// Init ///\\n\\n /// @notice Initialize local variables for the Hop Facet\\n /// @param configs Bridge configuration data\\n function initHop(Config[] calldata configs) external {\\n LibDiamond.enforceIsContractOwner();\\n\\n Storage storage s = getStorage();\\n\\n for (uint256 i = 0; i < configs.length; i++) {\\n if (configs[i].bridge == address(0)) {\\n revert InvalidConfig();\\n }\\n s.bridges[configs[i].assetId] = IHopBridge(configs[i].bridge);\\n }\\n\\n emit HopInitialized(configs);\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Register token and bridge\\n /// @param assetId Address of token\\n /// @param bridge Address of bridge for asset\\n function registerBridge(address assetId, address bridge) external {\\n LibDiamond.enforceIsContractOwner();\\n\\n Storage storage s = getStorage();\\n\\n if (bridge == address(0)) {\\n revert InvalidConfig();\\n }\\n\\n s.bridges[assetId] = IHopBridge(bridge);\\n\\n emit HopBridgeRegistered(assetId, bridge);\\n }\\n\\n /// @notice Bridges tokens via Hop Protocol\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _hopData data specific to Hop Protocol\\n function startBridgeTokensViaHop(\\n ILiFi.BridgeData memory _bridgeData,\\n HopData calldata _hopData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData, _hopData);\\n }\\n\\n /// @notice Performs a swap before bridging via Hop Protocol\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _hopData data specific to Hop Protocol\\n function swapAndStartBridgeTokensViaHop(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n HopData calldata _hopData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n _hopData.nativeFee\\n );\\n _startBridge(_bridgeData, _hopData);\\n }\\n\\n /// private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Hop Protocol\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _hopData data specific to Hop Protocol\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n HopData calldata _hopData\\n ) private {\\n address sendingAssetId = _bridgeData.sendingAssetId;\\n Storage storage s = getStorage();\\n IHopBridge bridge = s.bridges[sendingAssetId];\\n\\n // Give Hop approval to bridge tokens\\n LibAsset.maxApproveERC20(\\n IERC20(sendingAssetId),\\n address(bridge),\\n _bridgeData.minAmount\\n );\\n\\n uint256 value = LibAsset.isNativeAsset(address(sendingAssetId))\\n ? _hopData.nativeFee + _bridgeData.minAmount\\n : _hopData.nativeFee;\\n\\n if (block.chainid == 1 || block.chainid == 5) {\\n // Ethereum L1\\n bridge.sendToL2{ value: value }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline,\\n _hopData.relayer,\\n _hopData.relayerFee\\n );\\n } else {\\n // L2\\n // solhint-disable-next-line check-send-result\\n bridge.swapAndSend{ value: value }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.bonderFee,\\n _hopData.amountOutMin,\\n _hopData.deadline,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline\\n );\\n }\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @dev fetch local storage\\n function getStorage() private pure returns (Storage storage s) {\\n bytes32 namespace = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n s.slot := namespace\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IHopBridge.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IHopBridge {\\n function sendToL2(\\n uint256 chainId,\\n address recipient,\\n uint256 amount,\\n uint256 amountOutMin,\\n uint256 deadline,\\n address relayer,\\n uint256 relayerFee\\n ) external payable;\\n\\n function swapAndSend(\\n uint256 chainId,\\n address recipient,\\n uint256 amount,\\n uint256 bonderFee,\\n uint256 amountOutMin,\\n uint256 deadline,\\n uint256 destinationAmountOutMin,\\n uint256 destinationDeadline\\n ) external payable;\\n\\n function send(\\n uint256 chainId,\\n address recipient,\\n uint256 amount,\\n uint256 bonderFee,\\n uint256 amountOutMin,\\n uint256 deadline\\n ) external;\\n}\\n\\ninterface IL2AmmWrapper {\\n function bridge() external view returns (address);\\n\\n function l2CanonicalToken() external view returns (address);\\n\\n function hToken() external view returns (address);\\n\\n function exchangeAddress() external view returns (address);\\n}\\n\\ninterface ISwap {\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external returns (uint256);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyContractOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"bridge\",\"type\":\"address\"}],\"name\":\"HopBridgeRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"assetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"bridge\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct HopFacet.Config[]\",\"name\":\"configs\",\"type\":\"tuple[]\"}],\"name\":\"HopInitialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"assetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"bridge\",\"type\":\"address\"}],\"internalType\":\"struct HopFacet.Config[]\",\"name\":\"configs\",\"type\":\"tuple[]\"}],\"name\":\"initHop\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"assetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"bridge\",\"type\":\"address\"}],\"name\":\"registerBridge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacet.HopData\",\"name\":\"_hopData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaHop\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacet.HopData\",\"name\":\"_hopData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaHop\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "HopFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/HopFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IHopBridge } from \"../Interfaces/IHopBridge.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { InvalidConfig, AlreadyInitialized, NotInitialized } from \"../Errors/GenericErrors.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title Hop Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Hop\n/// @custom:version 2.0.0\ncontract HopFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n bytes32 internal constant NAMESPACE = keccak256(\"com.lifi.facets.hop\");\n\n /// Types ///\n\n struct Storage {\n mapping(address => IHopBridge) bridges;\n bool initialized; // no longer used but kept here to maintain the same storage layout\n }\n\n struct Config {\n address assetId;\n address bridge;\n }\n\n struct HopData {\n uint256 bonderFee;\n uint256 amountOutMin;\n uint256 deadline;\n uint256 destinationAmountOutMin;\n uint256 destinationDeadline;\n address relayer;\n uint256 relayerFee;\n uint256 nativeFee;\n }\n\n /// Events ///\n\n event HopInitialized(Config[] configs);\n event HopBridgeRegistered(address indexed assetId, address bridge);\n\n /// Init ///\n\n /// @notice Initialize local variables for the Hop Facet\n /// @param configs Bridge configuration data\n function initHop(Config[] calldata configs) external {\n LibDiamond.enforceIsContractOwner();\n\n Storage storage s = getStorage();\n\n for (uint256 i = 0; i < configs.length; i++) {\n if (configs[i].bridge == address(0)) {\n revert InvalidConfig();\n }\n s.bridges[configs[i].assetId] = IHopBridge(configs[i].bridge);\n }\n\n emit HopInitialized(configs);\n }\n\n /// External Methods ///\n\n /// @notice Register token and bridge\n /// @param assetId Address of token\n /// @param bridge Address of bridge for asset\n function registerBridge(address assetId, address bridge) external {\n LibDiamond.enforceIsContractOwner();\n\n Storage storage s = getStorage();\n\n if (bridge == address(0)) {\n revert InvalidConfig();\n }\n\n s.bridges[assetId] = IHopBridge(bridge);\n\n emit HopBridgeRegistered(assetId, bridge);\n }\n\n /// @notice Bridges tokens via Hop Protocol\n /// @param _bridgeData the core information needed for bridging\n /// @param _hopData data specific to Hop Protocol\n function startBridgeTokensViaHop(\n ILiFi.BridgeData memory _bridgeData,\n HopData calldata _hopData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData, _hopData);\n }\n\n /// @notice Performs a swap before bridging via Hop Protocol\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _hopData data specific to Hop Protocol\n function swapAndStartBridgeTokensViaHop(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n HopData calldata _hopData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n _hopData.nativeFee\n );\n _startBridge(_bridgeData, _hopData);\n }\n\n /// private Methods ///\n\n /// @dev Contains the business logic for the bridge via Hop Protocol\n /// @param _bridgeData the core information needed for bridging\n /// @param _hopData data specific to Hop Protocol\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n HopData calldata _hopData\n ) private {\n address sendingAssetId = _bridgeData.sendingAssetId;\n Storage storage s = getStorage();\n IHopBridge bridge = s.bridges[sendingAssetId];\n\n // Give Hop approval to bridge tokens\n LibAsset.maxApproveERC20(\n IERC20(sendingAssetId),\n address(bridge),\n _bridgeData.minAmount\n );\n\n uint256 value = LibAsset.isNativeAsset(address(sendingAssetId))\n ? _hopData.nativeFee + _bridgeData.minAmount\n : _hopData.nativeFee;\n\n if (block.chainid == 1 || block.chainid == 5) {\n // Ethereum L1\n bridge.sendToL2{ value: value }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline,\n _hopData.relayer,\n _hopData.relayerFee\n );\n } else {\n // L2\n // solhint-disable-next-line check-send-result\n bridge.swapAndSend{ value: value }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.bonderFee,\n _hopData.amountOutMin,\n _hopData.deadline,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline\n );\n }\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @dev fetch local storage\n function getStorage() private pure returns (Storage storage s) {\n bytes32 namespace = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n s.slot := namespace\n }\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IHopBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IHopBridge {\n function sendToL2(\n uint256 chainId,\n address recipient,\n uint256 amount,\n uint256 amountOutMin,\n uint256 deadline,\n address relayer,\n uint256 relayerFee\n ) external payable;\n\n function swapAndSend(\n uint256 chainId,\n address recipient,\n uint256 amount,\n uint256 bonderFee,\n uint256 amountOutMin,\n uint256 deadline,\n uint256 destinationAmountOutMin,\n uint256 destinationDeadline\n ) external payable;\n\n function send(\n uint256 chainId,\n address recipient,\n uint256 amount,\n uint256 bonderFee,\n uint256 amountOutMin,\n uint256 deadline\n ) external;\n}\n\ninterface IL2AmmWrapper {\n function bridge() external view returns (address);\n\n function l2CanonicalToken() external view returns (address);\n\n function hToken() external view returns (address);\n\n function exchangeAddress() external view returns (address);\n}\n\ninterface ISwap {\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +2.0.0 + Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... /HopFacetOptimized +0x7d507e6e89c52ae610b8d0151c8cb24c24e43bdb +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/HopFacetOptimized.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IHopBridge } from \\\"../Interfaces/IHopBridge.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\n\\n/// @title Hop Facet (Optimized)\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Hop\\n/// @custom:version 2.0.0\\ncontract HopFacetOptimized is ILiFi, SwapperV2 {\\n /// Types ///\\n\\n struct HopData {\\n uint256 bonderFee;\\n uint256 amountOutMin;\\n uint256 deadline;\\n uint256 destinationAmountOutMin;\\n uint256 destinationDeadline;\\n IHopBridge hopBridge;\\n address relayer;\\n uint256 relayerFee;\\n uint256 nativeFee;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Sets approval for the Hop Bridge to spend the specified token\\n /// @param bridges The Hop Bridges to approve\\n /// @param tokensToApprove The tokens to approve to approve to the Hop Bridges\\n function setApprovalForBridges(\\n address[] calldata bridges,\\n address[] calldata tokensToApprove\\n ) external {\\n LibDiamond.enforceIsContractOwner();\\n for (uint256 i; i < bridges.length; i++) {\\n // Give Hop approval to bridge tokens\\n LibAsset.maxApproveERC20(\\n IERC20(tokensToApprove[i]),\\n address(bridges[i]),\\n type(uint256).max\\n );\\n }\\n }\\n\\n /// @notice Bridges ERC20 tokens via Hop Protocol from L1\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _hopData data specific to Hop Protocol\\n function startBridgeTokensViaHopL1ERC20(\\n ILiFi.BridgeData calldata _bridgeData,\\n HopData calldata _hopData\\n ) external payable {\\n // Deposit assets\\n LibAsset.transferFromERC20(\\n _bridgeData.sendingAssetId,\\n msg.sender,\\n address(this),\\n _bridgeData.minAmount\\n );\\n // Bridge assets\\n _hopData.hopBridge.sendToL2{ value: _hopData.nativeFee }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline,\\n _hopData.relayer,\\n _hopData.relayerFee\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Bridges Native tokens via Hop Protocol from L1\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _hopData data specific to Hop Protocol\\n function startBridgeTokensViaHopL1Native(\\n ILiFi.BridgeData calldata _bridgeData,\\n HopData calldata _hopData\\n ) external payable {\\n // Bridge assets\\n _hopData.hopBridge.sendToL2{\\n value: _bridgeData.minAmount + _hopData.nativeFee\\n }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline,\\n _hopData.relayer,\\n _hopData.relayerFee\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging ERC20 tokens via Hop Protocol from L1\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _hopData data specific to Hop Protocol\\n function swapAndStartBridgeTokensViaHopL1ERC20(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n HopData calldata _hopData\\n ) external payable {\\n // Deposit and swap assets\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n _hopData.nativeFee\\n );\\n\\n // Bridge assets\\n _hopData.hopBridge.sendToL2{ value: _hopData.nativeFee }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline,\\n _hopData.relayer,\\n _hopData.relayerFee\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging Native tokens via Hop Protocol from L1\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _hopData data specific to Hop Protocol\\n function swapAndStartBridgeTokensViaHopL1Native(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n HopData calldata _hopData\\n ) external payable {\\n // Deposit and swap assets\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n _hopData.nativeFee\\n );\\n\\n // Bridge assets\\n _hopData.hopBridge.sendToL2{\\n value: _bridgeData.minAmount + _hopData.nativeFee\\n }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline,\\n _hopData.relayer,\\n _hopData.relayerFee\\n );\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Bridges ERC20 tokens via Hop Protocol from L2\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _hopData data specific to Hop Protocol\\n function startBridgeTokensViaHopL2ERC20(\\n ILiFi.BridgeData calldata _bridgeData,\\n HopData calldata _hopData\\n ) external {\\n // Deposit assets\\n LibAsset.transferFromERC20(\\n _bridgeData.sendingAssetId,\\n msg.sender,\\n address(this),\\n _bridgeData.minAmount\\n );\\n // Bridge assets\\n _hopData.hopBridge.swapAndSend(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.bonderFee,\\n _hopData.amountOutMin,\\n _hopData.deadline,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Bridges Native tokens via Hop Protocol from L2\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _hopData data specific to Hop Protocol\\n function startBridgeTokensViaHopL2Native(\\n ILiFi.BridgeData calldata _bridgeData,\\n HopData calldata _hopData\\n ) external payable {\\n // Bridge assets\\n _hopData.hopBridge.swapAndSend{ value: _bridgeData.minAmount }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.bonderFee,\\n _hopData.amountOutMin,\\n _hopData.deadline,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging ERC20 tokens via Hop Protocol from L2\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _hopData data specific to Hop Protocol\\n function swapAndStartBridgeTokensViaHopL2ERC20(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n HopData calldata _hopData\\n ) external payable {\\n // Deposit and swap assets\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n // Bridge assets\\n _hopData.hopBridge.swapAndSend(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.bonderFee,\\n _hopData.amountOutMin,\\n _hopData.deadline,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging Native tokens via Hop Protocol from L2\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _hopData data specific to Hop Protocol\\n function swapAndStartBridgeTokensViaHopL2Native(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n HopData calldata _hopData\\n ) external payable {\\n // Deposit and swap assets\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n // Bridge assets\\n _hopData.hopBridge.swapAndSend{ value: _bridgeData.minAmount }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.bonderFee,\\n _hopData.amountOutMin,\\n _hopData.deadline,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IHopBridge.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IHopBridge {\\n function sendToL2(\\n uint256 chainId,\\n address recipient,\\n uint256 amount,\\n uint256 amountOutMin,\\n uint256 deadline,\\n address relayer,\\n uint256 relayerFee\\n ) external payable;\\n\\n function swapAndSend(\\n uint256 chainId,\\n address recipient,\\n uint256 amount,\\n uint256 bonderFee,\\n uint256 amountOutMin,\\n uint256 deadline,\\n uint256 destinationAmountOutMin,\\n uint256 destinationDeadline\\n ) external payable;\\n\\n function send(\\n uint256 chainId,\\n address recipient,\\n uint256 amount,\\n uint256 bonderFee,\\n uint256 amountOutMin,\\n uint256 deadline\\n ) external;\\n}\\n\\ninterface IL2AmmWrapper {\\n function bridge() external view returns (address);\\n\\n function l2CanonicalToken() external view returns (address);\\n\\n function hToken() external view returns (address);\\n\\n function exchangeAddress() external view returns (address);\\n}\\n\\ninterface ISwap {\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external returns (uint256);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyContractOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"bridges\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"tokensToApprove\",\"type\":\"address[]\"}],\"name\":\"setApprovalForBridges\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"contract IHopBridge\",\"name\":\"hopBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacetOptimized.HopData\",\"name\":\"_hopData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaHopL1ERC20\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"contract IHopBridge\",\"name\":\"hopBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacetOptimized.HopData\",\"name\":\"_hopData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaHopL1Native\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"contract IHopBridge\",\"name\":\"hopBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacetOptimized.HopData\",\"name\":\"_hopData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaHopL2ERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"contract IHopBridge\",\"name\":\"hopBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacetOptimized.HopData\",\"name\":\"_hopData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaHopL2Native\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"contract IHopBridge\",\"name\":\"hopBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacetOptimized.HopData\",\"name\":\"_hopData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaHopL1ERC20\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"contract IHopBridge\",\"name\":\"hopBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacetOptimized.HopData\",\"name\":\"_hopData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaHopL1Native\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"contract IHopBridge\",\"name\":\"hopBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacetOptimized.HopData\",\"name\":\"_hopData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaHopL2ERC20\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"contract IHopBridge\",\"name\":\"hopBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacetOptimized.HopData\",\"name\":\"_hopData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaHopL2Native\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "HopFacetOptimized", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/HopFacetOptimized.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IHopBridge } from \"../Interfaces/IHopBridge.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\n\n/// @title Hop Facet (Optimized)\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Hop\n/// @custom:version 2.0.0\ncontract HopFacetOptimized is ILiFi, SwapperV2 {\n /// Types ///\n\n struct HopData {\n uint256 bonderFee;\n uint256 amountOutMin;\n uint256 deadline;\n uint256 destinationAmountOutMin;\n uint256 destinationDeadline;\n IHopBridge hopBridge;\n address relayer;\n uint256 relayerFee;\n uint256 nativeFee;\n }\n\n /// External Methods ///\n\n /// @notice Sets approval for the Hop Bridge to spend the specified token\n /// @param bridges The Hop Bridges to approve\n /// @param tokensToApprove The tokens to approve to approve to the Hop Bridges\n function setApprovalForBridges(\n address[] calldata bridges,\n address[] calldata tokensToApprove\n ) external {\n LibDiamond.enforceIsContractOwner();\n for (uint256 i; i < bridges.length; i++) {\n // Give Hop approval to bridge tokens\n LibAsset.maxApproveERC20(\n IERC20(tokensToApprove[i]),\n address(bridges[i]),\n type(uint256).max\n );\n }\n }\n\n /// @notice Bridges ERC20 tokens via Hop Protocol from L1\n /// @param _bridgeData the core information needed for bridging\n /// @param _hopData data specific to Hop Protocol\n function startBridgeTokensViaHopL1ERC20(\n ILiFi.BridgeData calldata _bridgeData,\n HopData calldata _hopData\n ) external payable {\n // Deposit assets\n LibAsset.transferFromERC20(\n _bridgeData.sendingAssetId,\n msg.sender,\n address(this),\n _bridgeData.minAmount\n );\n // Bridge assets\n _hopData.hopBridge.sendToL2{ value: _hopData.nativeFee }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline,\n _hopData.relayer,\n _hopData.relayerFee\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Bridges Native tokens via Hop Protocol from L1\n /// @param _bridgeData the core information needed for bridging\n /// @param _hopData data specific to Hop Protocol\n function startBridgeTokensViaHopL1Native(\n ILiFi.BridgeData calldata _bridgeData,\n HopData calldata _hopData\n ) external payable {\n // Bridge assets\n _hopData.hopBridge.sendToL2{\n value: _bridgeData.minAmount + _hopData.nativeFee\n }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline,\n _hopData.relayer,\n _hopData.relayerFee\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging ERC20 tokens via Hop Protocol from L1\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _hopData data specific to Hop Protocol\n function swapAndStartBridgeTokensViaHopL1ERC20(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n HopData calldata _hopData\n ) external payable {\n // Deposit and swap assets\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n _hopData.nativeFee\n );\n\n // Bridge assets\n _hopData.hopBridge.sendToL2{ value: _hopData.nativeFee }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline,\n _hopData.relayer,\n _hopData.relayerFee\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging Native tokens via Hop Protocol from L1\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _hopData data specific to Hop Protocol\n function swapAndStartBridgeTokensViaHopL1Native(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n HopData calldata _hopData\n ) external payable {\n // Deposit and swap assets\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n _hopData.nativeFee\n );\n\n // Bridge assets\n _hopData.hopBridge.sendToL2{\n value: _bridgeData.minAmount + _hopData.nativeFee\n }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline,\n _hopData.relayer,\n _hopData.relayerFee\n );\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Bridges ERC20 tokens via Hop Protocol from L2\n /// @param _bridgeData the core information needed for bridging\n /// @param _hopData data specific to Hop Protocol\n function startBridgeTokensViaHopL2ERC20(\n ILiFi.BridgeData calldata _bridgeData,\n HopData calldata _hopData\n ) external {\n // Deposit assets\n LibAsset.transferFromERC20(\n _bridgeData.sendingAssetId,\n msg.sender,\n address(this),\n _bridgeData.minAmount\n );\n // Bridge assets\n _hopData.hopBridge.swapAndSend(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.bonderFee,\n _hopData.amountOutMin,\n _hopData.deadline,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Bridges Native tokens via Hop Protocol from L2\n /// @param _bridgeData the core information needed for bridging\n /// @param _hopData data specific to Hop Protocol\n function startBridgeTokensViaHopL2Native(\n ILiFi.BridgeData calldata _bridgeData,\n HopData calldata _hopData\n ) external payable {\n // Bridge assets\n _hopData.hopBridge.swapAndSend{ value: _bridgeData.minAmount }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.bonderFee,\n _hopData.amountOutMin,\n _hopData.deadline,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging ERC20 tokens via Hop Protocol from L2\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _hopData data specific to Hop Protocol\n function swapAndStartBridgeTokensViaHopL2ERC20(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n HopData calldata _hopData\n ) external payable {\n // Deposit and swap assets\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n // Bridge assets\n _hopData.hopBridge.swapAndSend(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.bonderFee,\n _hopData.amountOutMin,\n _hopData.deadline,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging Native tokens via Hop Protocol from L2\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _hopData data specific to Hop Protocol\n function swapAndStartBridgeTokensViaHopL2Native(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n HopData calldata _hopData\n ) external payable {\n // Deposit and swap assets\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n // Bridge assets\n _hopData.hopBridge.swapAndSend{ value: _bridgeData.minAmount }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.bonderFee,\n _hopData.amountOutMin,\n _hopData.deadline,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IHopBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IHopBridge {\n function sendToL2(\n uint256 chainId,\n address recipient,\n uint256 amount,\n uint256 amountOutMin,\n uint256 deadline,\n address relayer,\n uint256 relayerFee\n ) external payable;\n\n function swapAndSend(\n uint256 chainId,\n address recipient,\n uint256 amount,\n uint256 bonderFee,\n uint256 amountOutMin,\n uint256 deadline,\n uint256 destinationAmountOutMin,\n uint256 destinationDeadline\n ) external payable;\n\n function send(\n uint256 chainId,\n address recipient,\n uint256 amount,\n uint256 bonderFee,\n uint256 amountOutMin,\n uint256 deadline\n ) external;\n}\n\ninterface IL2AmmWrapper {\n function bridge() external view returns (address);\n\n function l2CanonicalToken() external view returns (address);\n\n function hToken() external view returns (address);\n\n function exchangeAddress() external view returns (address);\n}\n\ninterface ISwap {\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +2.0.0 + Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \LIFuelFacet +0x66861f292099caf644f4a8b6091de49bec5e8a15 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/LIFuelFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LiFuelFeeCollector } from \\\"../Periphery/LiFuelFeeCollector.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title LIFuel Facet\\n/// @author Li.Finance (https://li.finance)\\n/// @notice Provides functionality for bridging gas through LIFuel\\n/// @custom:version 1.0.1\\ncontract LIFuelFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.facets.periphery_registry\\\");\\n string internal constant FEE_COLLECTOR_NAME = \\\"LiFuelFeeCollector\\\";\\n\\n /// Types ///\\n\\n struct Storage {\\n mapping(string => address) contracts;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via LIFuel Bridge\\n /// @param _bridgeData Data used purely for tracking and analytics\\n function startBridgeTokensViaLIFuel(\\n ILiFi.BridgeData memory _bridgeData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging via LIFuel Bridge\\n /// @param _bridgeData Data used purely for tracking and analytics\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n function swapAndStartBridgeTokensViaLIFuel(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n\\n _startBridge(_bridgeData);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via LIFuel Bridge\\n /// @param _bridgeData Data used purely for tracking and analytics\\n function _startBridge(ILiFi.BridgeData memory _bridgeData) private {\\n LiFuelFeeCollector liFuelFeeCollector = LiFuelFeeCollector(\\n getStorage().contracts[FEE_COLLECTOR_NAME]\\n );\\n\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n liFuelFeeCollector.collectNativeGasFees{\\n value: _bridgeData.minAmount\\n }(\\n _bridgeData.minAmount,\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver\\n );\\n } else {\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(liFuelFeeCollector),\\n _bridgeData.minAmount\\n );\\n\\n liFuelFeeCollector.collectTokenGasFees(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @dev fetch local storage\\n function getStorage() private pure returns (Storage storage s) {\\n bytes32 namespace = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n s.slot := namespace\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Periphery/LiFuelFeeCollector.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { TransferrableOwnership } from \\\"../Helpers/TransferrableOwnership.sol\\\";\\n\\n/// @title LiFuelFeeCollector\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for collecting fees for LiFuel\\n/// @custom:version 1.0.1\\ncontract LiFuelFeeCollector is TransferrableOwnership {\\n /// Errors ///\\n error TransferFailure();\\n error NotEnoughNativeForFees();\\n\\n /// Events ///\\n event GasFeesCollected(\\n address indexed token,\\n uint256 indexed chainId,\\n address indexed receiver,\\n uint256 feeAmount\\n );\\n\\n event FeesWithdrawn(\\n address indexed token,\\n address indexed to,\\n uint256 amount\\n );\\n\\n /// Constructor ///\\n\\n // solhint-disable-next-line no-empty-blocks\\n constructor(address _owner) TransferrableOwnership(_owner) {}\\n\\n /// External Methods ///\\n\\n /// @notice Collects gas fees\\n /// @param tokenAddress The address of the token to collect\\n /// @param feeAmount The amount of fees to collect\\n /// @param chainId The chain id of the destination chain\\n /// @param receiver The address to send gas to on the destination chain\\n function collectTokenGasFees(\\n address tokenAddress,\\n uint256 feeAmount,\\n uint256 chainId,\\n address receiver\\n ) external {\\n LibAsset.depositAsset(tokenAddress, feeAmount);\\n emit GasFeesCollected(tokenAddress, chainId, receiver, feeAmount);\\n }\\n\\n /// @notice Collects gas fees in native token\\n /// @param chainId The chain id of the destination chain\\n /// @param receiver The address to send gas to on destination chain\\n function collectNativeGasFees(\\n uint256 feeAmount,\\n uint256 chainId,\\n address receiver\\n ) external payable {\\n emit GasFeesCollected(\\n LibAsset.NULL_ADDRESS,\\n chainId,\\n receiver,\\n feeAmount\\n );\\n uint256 amountMinusFees = msg.value - feeAmount;\\n if (amountMinusFees > 0) {\\n (bool success, ) = msg.sender.call{ value: amountMinusFees }(\\\"\\\");\\n if (!success) {\\n revert TransferFailure();\\n }\\n }\\n }\\n\\n /// @notice Withdraws fees\\n /// @param tokenAddress The address of the token to withdraw fees for\\n function withdrawFees(address tokenAddress) external onlyOwner {\\n uint256 balance = LibAsset.getOwnBalance(tokenAddress);\\n LibAsset.transferAsset(tokenAddress, payable(msg.sender), balance);\\n emit FeesWithdrawn(tokenAddress, msg.sender, balance);\\n }\\n\\n /// @notice Batch withdraws fees\\n /// @param tokenAddresses The addresses of the tokens to withdraw fees for\\n function batchWithdrawFees(\\n address[] calldata tokenAddresses\\n ) external onlyOwner {\\n uint256 length = tokenAddresses.length;\\n uint256 balance;\\n for (uint256 i = 0; i < length; ) {\\n balance = LibAsset.getOwnBalance(tokenAddresses[i]);\\n LibAsset.transferAsset(\\n tokenAddresses[i],\\n payable(msg.sender),\\n balance\\n );\\n emit FeesWithdrawn(tokenAddresses[i], msg.sender, balance);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/TransferrableOwnership.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IERC173 } from \\\"../Interfaces/IERC173.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\n\\ncontract TransferrableOwnership is IERC173 {\\n address public owner;\\n address public pendingOwner;\\n\\n /// Errors ///\\n error UnAuthorized();\\n error NoNullOwner();\\n error NewOwnerMustNotBeSelf();\\n error NoPendingOwnershipTransfer();\\n error NotPendingOwner();\\n\\n /// Events ///\\n event OwnershipTransferRequested(\\n address indexed _from,\\n address indexed _to\\n );\\n\\n constructor(address initialOwner) {\\n owner = initialOwner;\\n }\\n\\n modifier onlyOwner() {\\n if (msg.sender != owner) revert UnAuthorized();\\n _;\\n }\\n\\n /// @notice Initiates transfer of ownership to a new address\\n /// @param _newOwner the address to transfer ownership to\\n function transferOwnership(address _newOwner) external onlyOwner {\\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\\n pendingOwner = _newOwner;\\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\\n }\\n\\n /// @notice Cancel transfer of ownership\\n function cancelOwnershipTransfer() external onlyOwner {\\n if (pendingOwner == LibAsset.NULL_ADDRESS)\\n revert NoPendingOwnershipTransfer();\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n\\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\\n function confirmOwnershipTransfer() external {\\n address _pendingOwner = pendingOwner;\\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\\n emit OwnershipTransferred(owner, _pendingOwner);\\n owner = _pendingOwner;\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IERC173.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\n/// @title ERC-173 Contract Ownership Standard\\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\\n/* is ERC165 */\\ninterface IERC173 {\\n /// @dev This emits when ownership of a contract changes.\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n /// @notice Get the address of the owner\\n /// @return owner_ The address of the owner.\\n function owner() external view returns (address owner_);\\n\\n /// @notice Set the address of the new owner of the contract\\n /// @dev Set _newOwner to address(0) to renounce any ownership.\\n /// @param _newOwner The address of the new owner of the contract\\n function transferOwnership(address _newOwner) external;\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaLIFuel\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"}],\"name\":\"swapAndStartBridgeTokensViaLIFuel\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "LIFuelFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/LIFuelFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LiFuelFeeCollector } from \"../Periphery/LiFuelFeeCollector.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title LIFuel Facet\n/// @author Li.Finance (https://li.finance)\n/// @notice Provides functionality for bridging gas through LIFuel\n/// @custom:version 1.0.1\ncontract LIFuelFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.facets.periphery_registry\");\n string internal constant FEE_COLLECTOR_NAME = \"LiFuelFeeCollector\";\n\n /// Types ///\n\n struct Storage {\n mapping(string => address) contracts;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via LIFuel Bridge\n /// @param _bridgeData Data used purely for tracking and analytics\n function startBridgeTokensViaLIFuel(\n ILiFi.BridgeData memory _bridgeData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging via LIFuel Bridge\n /// @param _bridgeData Data used purely for tracking and analytics\n /// @param _swapData An array of swap related data for performing swaps before bridging\n function swapAndStartBridgeTokensViaLIFuel(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n\n _startBridge(_bridgeData);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via LIFuel Bridge\n /// @param _bridgeData Data used purely for tracking and analytics\n function _startBridge(ILiFi.BridgeData memory _bridgeData) private {\n LiFuelFeeCollector liFuelFeeCollector = LiFuelFeeCollector(\n getStorage().contracts[FEE_COLLECTOR_NAME]\n );\n\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n liFuelFeeCollector.collectNativeGasFees{\n value: _bridgeData.minAmount\n }(\n _bridgeData.minAmount,\n _bridgeData.destinationChainId,\n _bridgeData.receiver\n );\n } else {\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(liFuelFeeCollector),\n _bridgeData.minAmount\n );\n\n liFuelFeeCollector.collectTokenGasFees(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n _bridgeData.destinationChainId,\n _bridgeData.receiver\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @dev fetch local storage\n function getStorage() private pure returns (Storage storage s) {\n bytes32 namespace = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n s.slot := namespace\n }\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Periphery/LiFuelFeeCollector.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { TransferrableOwnership } from \"../Helpers/TransferrableOwnership.sol\";\n\n/// @title LiFuelFeeCollector\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for collecting fees for LiFuel\n/// @custom:version 1.0.1\ncontract LiFuelFeeCollector is TransferrableOwnership {\n /// Errors ///\n error TransferFailure();\n error NotEnoughNativeForFees();\n\n /// Events ///\n event GasFeesCollected(\n address indexed token,\n uint256 indexed chainId,\n address indexed receiver,\n uint256 feeAmount\n );\n\n event FeesWithdrawn(\n address indexed token,\n address indexed to,\n uint256 amount\n );\n\n /// Constructor ///\n\n // solhint-disable-next-line no-empty-blocks\n constructor(address _owner) TransferrableOwnership(_owner) {}\n\n /// External Methods ///\n\n /// @notice Collects gas fees\n /// @param tokenAddress The address of the token to collect\n /// @param feeAmount The amount of fees to collect\n /// @param chainId The chain id of the destination chain\n /// @param receiver The address to send gas to on the destination chain\n function collectTokenGasFees(\n address tokenAddress,\n uint256 feeAmount,\n uint256 chainId,\n address receiver\n ) external {\n LibAsset.depositAsset(tokenAddress, feeAmount);\n emit GasFeesCollected(tokenAddress, chainId, receiver, feeAmount);\n }\n\n /// @notice Collects gas fees in native token\n /// @param chainId The chain id of the destination chain\n /// @param receiver The address to send gas to on destination chain\n function collectNativeGasFees(\n uint256 feeAmount,\n uint256 chainId,\n address receiver\n ) external payable {\n emit GasFeesCollected(\n LibAsset.NULL_ADDRESS,\n chainId,\n receiver,\n feeAmount\n );\n uint256 amountMinusFees = msg.value - feeAmount;\n if (amountMinusFees > 0) {\n (bool success, ) = msg.sender.call{ value: amountMinusFees }(\"\");\n if (!success) {\n revert TransferFailure();\n }\n }\n }\n\n /// @notice Withdraws fees\n /// @param tokenAddress The address of the token to withdraw fees for\n function withdrawFees(address tokenAddress) external onlyOwner {\n uint256 balance = LibAsset.getOwnBalance(tokenAddress);\n LibAsset.transferAsset(tokenAddress, payable(msg.sender), balance);\n emit FeesWithdrawn(tokenAddress, msg.sender, balance);\n }\n\n /// @notice Batch withdraws fees\n /// @param tokenAddresses The addresses of the tokens to withdraw fees for\n function batchWithdrawFees(\n address[] calldata tokenAddresses\n ) external onlyOwner {\n uint256 length = tokenAddresses.length;\n uint256 balance;\n for (uint256 i = 0; i < length; ) {\n balance = LibAsset.getOwnBalance(tokenAddresses[i]);\n LibAsset.transferAsset(\n tokenAddresses[i],\n payable(msg.sender),\n balance\n );\n emit FeesWithdrawn(tokenAddresses[i], msg.sender, balance);\n unchecked {\n ++i;\n }\n }\n }\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Helpers/TransferrableOwnership.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IERC173 } from \"../Interfaces/IERC173.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\n\ncontract TransferrableOwnership is IERC173 {\n address public owner;\n address public pendingOwner;\n\n /// Errors ///\n error UnAuthorized();\n error NoNullOwner();\n error NewOwnerMustNotBeSelf();\n error NoPendingOwnershipTransfer();\n error NotPendingOwner();\n\n /// Events ///\n event OwnershipTransferRequested(\n address indexed _from,\n address indexed _to\n );\n\n constructor(address initialOwner) {\n owner = initialOwner;\n }\n\n modifier onlyOwner() {\n if (msg.sender != owner) revert UnAuthorized();\n _;\n }\n\n /// @notice Initiates transfer of ownership to a new address\n /// @param _newOwner the address to transfer ownership to\n function transferOwnership(address _newOwner) external onlyOwner {\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\n pendingOwner = _newOwner;\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\n }\n\n /// @notice Cancel transfer of ownership\n function cancelOwnershipTransfer() external onlyOwner {\n if (pendingOwner == LibAsset.NULL_ADDRESS)\n revert NoPendingOwnershipTransfer();\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\n function confirmOwnershipTransfer() external {\n address _pendingOwner = pendingOwner;\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Interfaces/IERC173.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\n/// @title ERC-173 Contract Ownership Standard\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\n/* is ERC165 */\ninterface IERC173 {\n /// @dev This emits when ownership of a contract changes.\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n /// @notice Get the address of the owner\n /// @return owner_ The address of the owner.\n function owner() external view returns (address owner_);\n\n /// @notice Set the address of the new owner of the contract\n /// @dev Set _newOwner to address(0) to renounce any ownership.\n /// @param _newOwner The address of the new owner of the contract\n function transferOwnership(address _newOwner) external;\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +1.0.1 + Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... -CBridgeFacetPacked +0xe7bf43c55551b1036e796e7fd3b125d1f9903e2e +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/CBridgeFacetPacked.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ICBridge } from \\\"../Interfaces/ICBridge.sol\\\";\\nimport { CBridgeFacet } from \\\"./CBridgeFacet.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { ERC20, SafeTransferLib } from \\\"solmate/utils/SafeTransferLib.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { ContractCallNotAllowed, ExternalCallFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { TransferrableOwnership } from \\\"../Helpers/TransferrableOwnership.sol\\\";\\n\\n/// @title CBridge Facet Packed\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through CBridge\\n/// @custom:version 1.0.3\\ncontract CBridgeFacetPacked is ILiFi, TransferrableOwnership {\\n using SafeTransferLib for ERC20;\\n\\n /// Storage ///\\n\\n /// @notice The contract address of the cbridge on the source chain.\\n ICBridge private immutable cBridge;\\n\\n /// Events ///\\n\\n event LiFiCBridgeTransfer(bytes8 _transactionId);\\n\\n event CBridgeRefund(\\n address indexed _assetAddress,\\n address indexed _to,\\n uint256 amount\\n );\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _cBridge The contract address of the cbridge on the source chain.\\n constructor(\\n ICBridge _cBridge,\\n address _owner\\n ) TransferrableOwnership(_owner) {\\n cBridge = _cBridge;\\n }\\n\\n /// External Methods ///\\n\\n /// @dev Only meant to be called outside of the context of the diamond\\n /// @notice Sets approval for the CBridge Router to spend the specified token\\n /// @param tokensToApprove The tokens to approve to the CBridge Router\\n function setApprovalForBridge(\\n address[] calldata tokensToApprove\\n ) external onlyOwner {\\n for (uint256 i; i < tokensToApprove.length; i++) {\\n // Give CBridge approval to bridge tokens\\n LibAsset.maxApproveERC20(\\n IERC20(tokensToApprove[i]),\\n address(cBridge),\\n type(uint256).max\\n );\\n }\\n }\\n\\n // This is needed to receive native asset if a refund asset is a native asset\\n receive() external payable {}\\n\\n /// @notice Triggers a cBridge refund with calldata produced by cBridge API\\n /// @param _callTo The address to execute the calldata on\\n /// @param _callData The data to execute\\n /// @param _assetAddress Asset to be withdrawn\\n /// @param _to Address to withdraw to\\n /// @param _amount Amount of asset to withdraw\\n function triggerRefund(\\n address payable _callTo,\\n bytes calldata _callData,\\n address _assetAddress,\\n address _to,\\n uint256 _amount\\n ) external onlyOwner {\\n // make sure that callTo address is either of the cBridge addresses\\n if (address(cBridge) != _callTo) {\\n revert ContractCallNotAllowed();\\n }\\n\\n // call contract\\n bool success;\\n (success, ) = _callTo.call(_callData);\\n if (!success) {\\n revert ExternalCallFailed();\\n }\\n\\n // forward funds to _to address and emit event\\n address sendTo = (LibUtil.isZeroAddress(_to)) ? msg.sender : _to;\\n LibAsset.transferAsset(_assetAddress, payable(sendTo), _amount);\\n emit CBridgeRefund(_assetAddress, sendTo, _amount);\\n }\\n\\n /// @notice Bridges Native tokens via cBridge (packed)\\n /// No params, all data will be extracted from manually encoded callData\\n function startBridgeTokensViaCBridgeNativePacked() external payable {\\n cBridge.sendNative{ value: msg.value }(\\n address(bytes20(msg.data[12:32])), // receiver\\n msg.value, // amount\\n uint64(uint32(bytes4(msg.data[32:36]))), // destinationChainId\\n uint64(uint32(bytes4(msg.data[36:40]))), // nonce\\n uint32(bytes4(msg.data[40:44])) // maxSlippage\\n );\\n\\n emit LiFiCBridgeTransfer(bytes8(msg.data[4:12])); // transactionId\\n }\\n\\n /// @notice Bridges native tokens via cBridge\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param nonce A number input to guarantee uniqueness of transferId.\\n /// @param maxSlippage Destination swap minimal accepted amount\\n function startBridgeTokensViaCBridgeNativeMin(\\n bytes32 transactionId,\\n address receiver,\\n uint64 destinationChainId,\\n uint64 nonce,\\n uint32 maxSlippage\\n ) external payable {\\n cBridge.sendNative{ value: msg.value }(\\n receiver,\\n msg.value,\\n destinationChainId,\\n nonce,\\n maxSlippage\\n );\\n\\n emit LiFiCBridgeTransfer(bytes8(transactionId));\\n }\\n\\n /// @notice Bridges ERC20 tokens via cBridge\\n /// No params, all data will be extracted from manually encoded callData\\n function startBridgeTokensViaCBridgeERC20Packed() external {\\n address sendingAssetId = address(bytes20(msg.data[36:56]));\\n uint256 amount = uint256(uint128(bytes16(msg.data[56:72])));\\n\\n // Deposit assets\\n ERC20(sendingAssetId).safeTransferFrom(\\n msg.sender,\\n address(this),\\n amount\\n );\\n\\n // Bridge assets\\n // solhint-disable-next-line check-send-result\\n cBridge.send(\\n address(bytes20(msg.data[12:32])), // receiver\\n sendingAssetId, // sendingAssetId\\n amount, // amount\\n uint64(uint32(bytes4(msg.data[32:36]))), // destinationChainId\\n uint64(uint32(bytes4(msg.data[72:76]))), // nonce\\n uint32(bytes4(msg.data[76:80])) // maxSlippage\\n );\\n\\n emit LiFiCBridgeTransfer(bytes8(msg.data[4:12]));\\n }\\n\\n /// @notice Bridges ERC20 tokens via cBridge\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param sendingAssetId Address of the source asset to bridge\\n /// @param amount Amount of the source asset to bridge\\n /// @param nonce A number input to guarantee uniqueness of transferId\\n /// @param maxSlippage Destination swap minimal accepted amount\\n function startBridgeTokensViaCBridgeERC20Min(\\n bytes32 transactionId,\\n address receiver,\\n uint64 destinationChainId,\\n address sendingAssetId,\\n uint256 amount,\\n uint64 nonce,\\n uint32 maxSlippage\\n ) external {\\n // Deposit assets\\n ERC20(sendingAssetId).safeTransferFrom(\\n msg.sender,\\n address(this),\\n amount\\n );\\n\\n // Bridge assets\\n // solhint-disable-next-line check-send-result\\n cBridge.send(\\n receiver,\\n sendingAssetId,\\n amount,\\n destinationChainId,\\n nonce,\\n maxSlippage\\n );\\n\\n emit LiFiCBridgeTransfer(bytes8(transactionId));\\n }\\n\\n /// Encoder/Decoders ///\\n\\n /// @notice Encodes calldata for startBridgeTokensViaCBridgeNativePacked\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param nonce A number input to guarantee uniqueness of transferId.\\n /// @param maxSlippage Destination swap minimal accepted amount\\n function encode_startBridgeTokensViaCBridgeNativePacked(\\n bytes32 transactionId,\\n address receiver,\\n uint64 destinationChainId,\\n uint64 nonce,\\n uint32 maxSlippage\\n ) external pure returns (bytes memory) {\\n require(\\n destinationChainId <= type(uint32).max,\\n \\\"destinationChainId value passed too big to fit in uint32\\\"\\n );\\n require(\\n nonce <= type(uint32).max,\\n \\\"nonce value passed too big to fit in uint32\\\"\\n );\\n\\n return\\n bytes.concat(\\n CBridgeFacetPacked\\n .startBridgeTokensViaCBridgeNativePacked\\n .selector,\\n bytes8(transactionId),\\n bytes20(receiver),\\n bytes4(uint32(destinationChainId)),\\n bytes4(uint32(nonce)),\\n bytes4(maxSlippage)\\n );\\n }\\n\\n /// @notice Decodes calldata for startBridgeTokensViaCBridgeNativePacked\\n /// @param _data the calldata to decode\\n function decode_startBridgeTokensViaCBridgeNativePacked(\\n bytes calldata _data\\n )\\n external\\n pure\\n returns (BridgeData memory, CBridgeFacet.CBridgeData memory)\\n {\\n require(\\n _data.length >= 44,\\n \\\"data passed in is not the correct length\\\"\\n );\\n\\n BridgeData memory bridgeData;\\n CBridgeFacet.CBridgeData memory cBridgeData;\\n\\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\\n bridgeData.receiver = address(bytes20(_data[12:32]));\\n bridgeData.destinationChainId = uint64(uint32(bytes4(_data[32:36])));\\n cBridgeData.nonce = uint64(uint32(bytes4(_data[36:40])));\\n cBridgeData.maxSlippage = uint32(bytes4(_data[40:44]));\\n\\n return (bridgeData, cBridgeData);\\n }\\n\\n /// @notice Encodes calldata for startBridgeTokensViaCBridgeERC20Packed\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param sendingAssetId Address of the source asset to bridge\\n /// @param minAmount Amount of the source asset to bridge\\n /// @param nonce A number input to guarantee uniqueness of transferId\\n /// @param maxSlippage Destination swap minimal accepted amount\\n function encode_startBridgeTokensViaCBridgeERC20Packed(\\n bytes32 transactionId,\\n address receiver,\\n uint64 destinationChainId,\\n address sendingAssetId,\\n uint256 minAmount,\\n uint64 nonce,\\n uint32 maxSlippage\\n ) external pure returns (bytes memory) {\\n require(\\n destinationChainId <= type(uint32).max,\\n \\\"destinationChainId value passed too big to fit in uint32\\\"\\n );\\n require(\\n minAmount <= type(uint128).max,\\n \\\"amount value passed too big to fit in uint128\\\"\\n );\\n require(\\n nonce <= type(uint32).max,\\n \\\"nonce value passed too big to fit in uint32\\\"\\n );\\n\\n return\\n bytes.concat(\\n CBridgeFacetPacked\\n .startBridgeTokensViaCBridgeERC20Packed\\n .selector,\\n bytes8(transactionId),\\n bytes20(receiver),\\n bytes4(uint32(destinationChainId)),\\n bytes20(sendingAssetId),\\n bytes16(uint128(minAmount)),\\n bytes4(uint32(nonce)),\\n bytes4(maxSlippage)\\n );\\n }\\n\\n function decode_startBridgeTokensViaCBridgeERC20Packed(\\n bytes calldata _data\\n )\\n external\\n pure\\n returns (BridgeData memory, CBridgeFacet.CBridgeData memory)\\n {\\n require(_data.length >= 80, \\\"data passed is not the correct length\\\");\\n\\n BridgeData memory bridgeData;\\n CBridgeFacet.CBridgeData memory cBridgeData;\\n\\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\\n bridgeData.receiver = address(bytes20(_data[12:32]));\\n bridgeData.destinationChainId = uint64(uint32(bytes4(_data[32:36])));\\n bridgeData.sendingAssetId = address(bytes20(_data[36:56]));\\n bridgeData.minAmount = uint256(uint128(bytes16(_data[56:72])));\\n cBridgeData.nonce = uint64(uint32(bytes4(_data[72:76])));\\n cBridgeData.maxSlippage = uint32(bytes4(_data[76:80]));\\n\\n return (bridgeData, cBridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ICBridge.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ICBridge {\\n /// @notice Send a cross-chain transfer via the liquidity pool-based bridge.\\n /// @dev This function DOES NOT SUPPORT fee-on-transfer / rebasing tokens.\\n /// @param _receiver The address of the receiver.\\n /// @param _token The address of the token.\\n /// @param _amount The amount of the transfer.\\n /// @param _dstChainId The destination chain ID.\\n /// @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\\n /// @param _maxSlippage The max slippage accepted, given as percentage in point (pip).\\n /// Eg. 5000 means 0.5%. Must be greater than minimalMaxSlippage.\\n /// Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount\\n /// or the transfer can be refunded.\\n function send(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce,\\n uint32 _maxSlippage\\n ) external;\\n\\n /// @notice Send a cross-chain transfer via the liquidity pool-based bridge using the native token.\\n /// @param _receiver The address of the receiver.\\n /// @param _amount The amount of the transfer.\\n /// @param _dstChainId The destination chain ID.\\n /// @param _nonce A unique number. Can be timestamp in practice.\\n /// @param _maxSlippage The max slippage accepted, given as percentage in point (pip).\\n /// Eg. 5000 means 0.5%. Must be greater than minimalMaxSlippage.\\n /// Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount\\n /// or the transfer can be refunded.\\n function sendNative(\\n address _receiver,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce,\\n uint32 _maxSlippage\\n ) external payable;\\n}\\n\"\r\n },\r\n \"src/Facets/CBridgeFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAccess } from \\\"../Libraries/LibAccess.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { ICBridge } from \\\"../Interfaces/ICBridge.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { ContractCallNotAllowed, ExternalCallFailed } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title CBridge Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through CBridge\\n/// @custom:version 1.0.0\\ncontract CBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n /// @notice The contract address of the cbridge on the source chain.\\n ICBridge private immutable cBridge;\\n\\n /// Types ///\\n\\n /// @param maxSlippage The max slippage accepted, given as percentage in point (pip).\\n /// @param nonce A number input to guarantee uniqueness of transferId.\\n /// Can be timestamp in practice.\\n struct CBridgeData {\\n uint32 maxSlippage;\\n uint64 nonce;\\n }\\n\\n /// Events ///\\n event CBridgeRefund(\\n address indexed _assetAddress,\\n address indexed _to,\\n uint256 amount\\n );\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _cBridge The contract address of the cbridge on the source chain.\\n constructor(ICBridge _cBridge) {\\n cBridge = _cBridge;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via CBridge\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _cBridgeData data specific to CBridge\\n function startBridgeTokensViaCBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n CBridgeData calldata _cBridgeData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData, _cBridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging via CBridge\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _cBridgeData data specific to CBridge\\n function swapAndStartBridgeTokensViaCBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n CBridgeData calldata _cBridgeData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n _startBridge(_bridgeData, _cBridgeData);\\n }\\n\\n /// @notice Triggers a cBridge refund with calldata produced by cBridge API\\n /// @param _callTo The address to execute the calldata on\\n /// @param _callData The data to execute\\n /// @param _assetAddress Asset to be withdrawn\\n /// @param _to Address to withdraw to\\n /// @param _amount Amount of asset to withdraw\\n function triggerRefund(\\n address payable _callTo,\\n bytes calldata _callData,\\n address _assetAddress,\\n address _to,\\n uint256 _amount\\n ) external {\\n if (msg.sender != LibDiamond.contractOwner()) {\\n LibAccess.enforceAccessControl();\\n }\\n\\n // make sure that callTo address is either of the cBridge addresses\\n if (address(cBridge) != _callTo) {\\n revert ContractCallNotAllowed();\\n }\\n\\n // call contract\\n bool success;\\n (success, ) = _callTo.call(_callData);\\n if (!success) {\\n revert ExternalCallFailed();\\n }\\n\\n // forward funds to _to address and emit event\\n address sendTo = (LibUtil.isZeroAddress(_to)) ? msg.sender : _to;\\n LibAsset.transferAsset(_assetAddress, payable(sendTo), _amount);\\n emit CBridgeRefund(_assetAddress, sendTo, _amount);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via CBridge\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _cBridgeData data specific to CBridge\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n CBridgeData calldata _cBridgeData\\n ) private {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n cBridge.sendNative{ value: _bridgeData.minAmount }(\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _cBridgeData.nonce,\\n _cBridgeData.maxSlippage\\n );\\n } else {\\n // Give CBridge approval to bridge tokens\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(cBridge),\\n _bridgeData.minAmount\\n );\\n // solhint-disable check-send-result\\n cBridge.send(\\n _bridgeData.receiver,\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _cBridgeData.nonce,\\n _cBridgeData.maxSlippage\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"lib/solmate/src/utils/SafeTransferLib.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\nimport {ERC20} from \\\"../tokens/ERC20.sol\\\";\\n\\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\\nlibrary SafeTransferLib {\\n /*//////////////////////////////////////////////////////////////\\n ETH OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferETH(address to, uint256 amount) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Transfer the ETH and store if it succeeded or not.\\n success := call(gas(), to, amount, 0, 0, 0, 0)\\n }\\n\\n require(success, \\\"ETH_TRANSFER_FAILED\\\");\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferFrom(\\n ERC20 token,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), from) // Append the \\\"from\\\" argument.\\n mstore(add(freeMemoryPointer, 36), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 68), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FROM_FAILED\\\");\\n }\\n\\n function safeTransfer(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FAILED\\\");\\n }\\n\\n function safeApprove(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"APPROVE_FAILED\\\");\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/TransferrableOwnership.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IERC173 } from \\\"../Interfaces/IERC173.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\n\\ncontract TransferrableOwnership is IERC173 {\\n address public owner;\\n address public pendingOwner;\\n\\n /// Errors ///\\n error UnAuthorized();\\n error NoNullOwner();\\n error NewOwnerMustNotBeSelf();\\n error NoPendingOwnershipTransfer();\\n error NotPendingOwner();\\n\\n /// Events ///\\n event OwnershipTransferRequested(\\n address indexed _from,\\n address indexed _to\\n );\\n\\n constructor(address initialOwner) {\\n owner = initialOwner;\\n }\\n\\n modifier onlyOwner() {\\n if (msg.sender != owner) revert UnAuthorized();\\n _;\\n }\\n\\n /// @notice Initiates transfer of ownership to a new address\\n /// @param _newOwner the address to transfer ownership to\\n function transferOwnership(address _newOwner) external onlyOwner {\\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\\n pendingOwner = _newOwner;\\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\\n }\\n\\n /// @notice Cancel transfer of ownership\\n function cancelOwnershipTransfer() external onlyOwner {\\n if (pendingOwner == LibAsset.NULL_ADDRESS)\\n revert NoPendingOwnershipTransfer();\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n\\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\\n function confirmOwnershipTransfer() external {\\n address _pendingOwner = pendingOwner;\\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\\n emit OwnershipTransferred(owner, _pendingOwner);\\n owner = _pendingOwner;\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAccess.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { CannotAuthoriseSelf, UnAuthorized } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Access Library\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for managing method level access control\\nlibrary LibAccess {\\n /// Types ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.access.management\\\");\\n\\n /// Storage ///\\n struct AccessStorage {\\n mapping(bytes4 => mapping(address => bool)) execAccess;\\n }\\n\\n /// Events ///\\n event AccessGranted(address indexed account, bytes4 indexed method);\\n event AccessRevoked(address indexed account, bytes4 indexed method);\\n\\n /// @dev Fetch local storage\\n function accessStorage()\\n internal\\n pure\\n returns (AccessStorage storage accStor)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n accStor.slot := position\\n }\\n }\\n\\n /// @notice Gives an address permission to execute a method\\n /// @param selector The method selector to execute\\n /// @param executor The address to grant permission to\\n function addAccess(bytes4 selector, address executor) internal {\\n if (executor == address(this)) {\\n revert CannotAuthoriseSelf();\\n }\\n AccessStorage storage accStor = accessStorage();\\n accStor.execAccess[selector][executor] = true;\\n emit AccessGranted(executor, selector);\\n }\\n\\n /// @notice Revokes permission to execute a method\\n /// @param selector The method selector to execute\\n /// @param executor The address to revoke permission from\\n function removeAccess(bytes4 selector, address executor) internal {\\n AccessStorage storage accStor = accessStorage();\\n accStor.execAccess[selector][executor] = false;\\n emit AccessRevoked(executor, selector);\\n }\\n\\n /// @notice Enforces access control by reverting if `msg.sender`\\n /// has not been given permission to execute `msg.sig`\\n function enforceAccessControl() internal view {\\n AccessStorage storage accStor = accessStorage();\\n if (accStor.execAccess[msg.sig][msg.sender] != true)\\n revert UnAuthorized();\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"lib/solmate/src/tokens/ERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\\nabstract contract ERC20 {\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /*//////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string public name;\\n\\n string public symbol;\\n\\n uint8 public immutable decimals;\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 public totalSupply;\\n\\n mapping(address => uint256) public balanceOf;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 internal immutable INITIAL_CHAIN_ID;\\n\\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\\n\\n mapping(address => uint256) public nonces;\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n constructor(\\n string memory _name,\\n string memory _symbol,\\n uint8 _decimals\\n ) {\\n name = _name;\\n symbol = _symbol;\\n decimals = _decimals;\\n\\n INITIAL_CHAIN_ID = block.chainid;\\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function approve(address spender, uint256 amount) public virtual returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n\\n return true;\\n }\\n\\n function transfer(address to, uint256 amount) public virtual returns (bool) {\\n balanceOf[msg.sender] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(msg.sender, to, amount);\\n\\n return true;\\n }\\n\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual returns (bool) {\\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\\n\\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\\n\\n balanceOf[from] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n return true;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 LOGIC\\n //////////////////////////////////////////////////////////////*/\\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 ) public virtual {\\n require(deadline >= block.timestamp, \\\"PERMIT_DEADLINE_EXPIRED\\\");\\n\\n // Unchecked because the only math done is incrementing\\n // the owner's nonce which cannot realistically overflow.\\n unchecked {\\n address recoveredAddress = ecrecover(\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR(),\\n keccak256(\\n abi.encode(\\n keccak256(\\n \\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\"\\n ),\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n require(recoveredAddress != address(0) && recoveredAddress == owner, \\\"INVALID_SIGNER\\\");\\n\\n allowance[recoveredAddress][spender] = value;\\n }\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\\n }\\n\\n function computeDomainSeparator() internal view virtual returns (bytes32) {\\n return\\n keccak256(\\n abi.encode(\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"),\\n keccak256(bytes(name)),\\n keccak256(\\\"1\\\"),\\n block.chainid,\\n address(this)\\n )\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _mint(address to, uint256 amount) internal virtual {\\n totalSupply += amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(address(0), to, amount);\\n }\\n\\n function _burn(address from, uint256 amount) internal virtual {\\n balanceOf[from] -= amount;\\n\\n // Cannot underflow because a user's balance\\n // will never be larger than the total supply.\\n unchecked {\\n totalSupply -= amount;\\n }\\n\\n emit Transfer(from, address(0), amount);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n },\r\n \"src/Interfaces/IERC173.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\n/// @title ERC-173 Contract Ownership Standard\\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\\n/* is ERC165 */\\ninterface IERC173 {\\n /// @dev This emits when ownership of a contract changes.\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n /// @notice Get the address of the owner\\n /// @return owner_ The address of the owner.\\n function owner() external view returns (address owner_);\\n\\n /// @notice Set the address of the new owner of the contract\\n /// @dev Set _newOwner to address(0) to renounce any ownership.\\n /// @param _newOwner The address of the new owner of the contract\\n function transferOwnership(address _newOwner) external;\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract ICBridge\",\"name\":\"_cBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExternalCallFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NewOwnerMustNotBeSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoNullOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoPendingOwnershipTransfer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotPendingOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnAuthorized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"CBridgeRefund\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes8\",\"name\":\"_transactionId\",\"type\":\"bytes8\"}],\"name\":\"LiFiCBridgeTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"cancelOwnershipTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"confirmOwnershipTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"decode_startBridgeTokensViaCBridgeERC20Packed\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSlippage\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"struct CBridgeFacet.CBridgeData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"decode_startBridgeTokensViaCBridgeNativePacked\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSlippage\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"struct CBridgeFacet.CBridgeData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destinationChainId\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"maxSlippage\",\"type\":\"uint32\"}],\"name\":\"encode_startBridgeTokensViaCBridgeERC20Packed\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destinationChainId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"maxSlippage\",\"type\":\"uint32\"}],\"name\":\"encode_startBridgeTokensViaCBridgeNativePacked\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokensToApprove\",\"type\":\"address[]\"}],\"name\":\"setApprovalForBridge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destinationChainId\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"maxSlippage\",\"type\":\"uint32\"}],\"name\":\"startBridgeTokensViaCBridgeERC20Min\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBridgeTokensViaCBridgeERC20Packed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destinationChainId\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"maxSlippage\",\"type\":\"uint32\"}],\"name\":\"startBridgeTokensViaCBridgeNativeMin\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBridgeTokensViaCBridgeNativePacked\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_callTo\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_callData\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"_assetAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"triggerRefund\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + ContractName: "CBridgeFacetPacked", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000005427fefa711eff984124bfbb1ab6fbf5e3da182000000000000000000000000011f11121df7256c40339393b0fb045321022ce44", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/CBridgeFacetPacked.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ICBridge } from \"../Interfaces/ICBridge.sol\";\nimport { CBridgeFacet } from \"./CBridgeFacet.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { ERC20, SafeTransferLib } from \"solmate/utils/SafeTransferLib.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { ContractCallNotAllowed, ExternalCallFailed } from \"../Errors/GenericErrors.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { TransferrableOwnership } from \"../Helpers/TransferrableOwnership.sol\";\n\n/// @title CBridge Facet Packed\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through CBridge\n/// @custom:version 1.0.3\ncontract CBridgeFacetPacked is ILiFi, TransferrableOwnership {\n using SafeTransferLib for ERC20;\n\n /// Storage ///\n\n /// @notice The contract address of the cbridge on the source chain.\n ICBridge private immutable cBridge;\n\n /// Events ///\n\n event LiFiCBridgeTransfer(bytes8 _transactionId);\n\n event CBridgeRefund(\n address indexed _assetAddress,\n address indexed _to,\n uint256 amount\n );\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _cBridge The contract address of the cbridge on the source chain.\n constructor(\n ICBridge _cBridge,\n address _owner\n ) TransferrableOwnership(_owner) {\n cBridge = _cBridge;\n }\n\n /// External Methods ///\n\n /// @dev Only meant to be called outside of the context of the diamond\n /// @notice Sets approval for the CBridge Router to spend the specified token\n /// @param tokensToApprove The tokens to approve to the CBridge Router\n function setApprovalForBridge(\n address[] calldata tokensToApprove\n ) external onlyOwner {\n for (uint256 i; i < tokensToApprove.length; i++) {\n // Give CBridge approval to bridge tokens\n LibAsset.maxApproveERC20(\n IERC20(tokensToApprove[i]),\n address(cBridge),\n type(uint256).max\n );\n }\n }\n\n // This is needed to receive native asset if a refund asset is a native asset\n receive() external payable {}\n\n /// @notice Triggers a cBridge refund with calldata produced by cBridge API\n /// @param _callTo The address to execute the calldata on\n /// @param _callData The data to execute\n /// @param _assetAddress Asset to be withdrawn\n /// @param _to Address to withdraw to\n /// @param _amount Amount of asset to withdraw\n function triggerRefund(\n address payable _callTo,\n bytes calldata _callData,\n address _assetAddress,\n address _to,\n uint256 _amount\n ) external onlyOwner {\n // make sure that callTo address is either of the cBridge addresses\n if (address(cBridge) != _callTo) {\n revert ContractCallNotAllowed();\n }\n\n // call contract\n bool success;\n (success, ) = _callTo.call(_callData);\n if (!success) {\n revert ExternalCallFailed();\n }\n\n // forward funds to _to address and emit event\n address sendTo = (LibUtil.isZeroAddress(_to)) ? msg.sender : _to;\n LibAsset.transferAsset(_assetAddress, payable(sendTo), _amount);\n emit CBridgeRefund(_assetAddress, sendTo, _amount);\n }\n\n /// @notice Bridges Native tokens via cBridge (packed)\n /// No params, all data will be extracted from manually encoded callData\n function startBridgeTokensViaCBridgeNativePacked() external payable {\n cBridge.sendNative{ value: msg.value }(\n address(bytes20(msg.data[12:32])), // receiver\n msg.value, // amount\n uint64(uint32(bytes4(msg.data[32:36]))), // destinationChainId\n uint64(uint32(bytes4(msg.data[36:40]))), // nonce\n uint32(bytes4(msg.data[40:44])) // maxSlippage\n );\n\n emit LiFiCBridgeTransfer(bytes8(msg.data[4:12])); // transactionId\n }\n\n /// @notice Bridges native tokens via cBridge\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param nonce A number input to guarantee uniqueness of transferId.\n /// @param maxSlippage Destination swap minimal accepted amount\n function startBridgeTokensViaCBridgeNativeMin(\n bytes32 transactionId,\n address receiver,\n uint64 destinationChainId,\n uint64 nonce,\n uint32 maxSlippage\n ) external payable {\n cBridge.sendNative{ value: msg.value }(\n receiver,\n msg.value,\n destinationChainId,\n nonce,\n maxSlippage\n );\n\n emit LiFiCBridgeTransfer(bytes8(transactionId));\n }\n\n /// @notice Bridges ERC20 tokens via cBridge\n /// No params, all data will be extracted from manually encoded callData\n function startBridgeTokensViaCBridgeERC20Packed() external {\n address sendingAssetId = address(bytes20(msg.data[36:56]));\n uint256 amount = uint256(uint128(bytes16(msg.data[56:72])));\n\n // Deposit assets\n ERC20(sendingAssetId).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n\n // Bridge assets\n // solhint-disable-next-line check-send-result\n cBridge.send(\n address(bytes20(msg.data[12:32])), // receiver\n sendingAssetId, // sendingAssetId\n amount, // amount\n uint64(uint32(bytes4(msg.data[32:36]))), // destinationChainId\n uint64(uint32(bytes4(msg.data[72:76]))), // nonce\n uint32(bytes4(msg.data[76:80])) // maxSlippage\n );\n\n emit LiFiCBridgeTransfer(bytes8(msg.data[4:12]));\n }\n\n /// @notice Bridges ERC20 tokens via cBridge\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param sendingAssetId Address of the source asset to bridge\n /// @param amount Amount of the source asset to bridge\n /// @param nonce A number input to guarantee uniqueness of transferId\n /// @param maxSlippage Destination swap minimal accepted amount\n function startBridgeTokensViaCBridgeERC20Min(\n bytes32 transactionId,\n address receiver,\n uint64 destinationChainId,\n address sendingAssetId,\n uint256 amount,\n uint64 nonce,\n uint32 maxSlippage\n ) external {\n // Deposit assets\n ERC20(sendingAssetId).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n\n // Bridge assets\n // solhint-disable-next-line check-send-result\n cBridge.send(\n receiver,\n sendingAssetId,\n amount,\n destinationChainId,\n nonce,\n maxSlippage\n );\n\n emit LiFiCBridgeTransfer(bytes8(transactionId));\n }\n\n /// Encoder/Decoders ///\n\n /// @notice Encodes calldata for startBridgeTokensViaCBridgeNativePacked\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param nonce A number input to guarantee uniqueness of transferId.\n /// @param maxSlippage Destination swap minimal accepted amount\n function encode_startBridgeTokensViaCBridgeNativePacked(\n bytes32 transactionId,\n address receiver,\n uint64 destinationChainId,\n uint64 nonce,\n uint32 maxSlippage\n ) external pure returns (bytes memory) {\n require(\n destinationChainId <= type(uint32).max,\n \"destinationChainId value passed too big to fit in uint32\"\n );\n require(\n nonce <= type(uint32).max,\n \"nonce value passed too big to fit in uint32\"\n );\n\n return\n bytes.concat(\n CBridgeFacetPacked\n .startBridgeTokensViaCBridgeNativePacked\n .selector,\n bytes8(transactionId),\n bytes20(receiver),\n bytes4(uint32(destinationChainId)),\n bytes4(uint32(nonce)),\n bytes4(maxSlippage)\n );\n }\n\n /// @notice Decodes calldata for startBridgeTokensViaCBridgeNativePacked\n /// @param _data the calldata to decode\n function decode_startBridgeTokensViaCBridgeNativePacked(\n bytes calldata _data\n )\n external\n pure\n returns (BridgeData memory, CBridgeFacet.CBridgeData memory)\n {\n require(\n _data.length >= 44,\n \"data passed in is not the correct length\"\n );\n\n BridgeData memory bridgeData;\n CBridgeFacet.CBridgeData memory cBridgeData;\n\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\n bridgeData.receiver = address(bytes20(_data[12:32]));\n bridgeData.destinationChainId = uint64(uint32(bytes4(_data[32:36])));\n cBridgeData.nonce = uint64(uint32(bytes4(_data[36:40])));\n cBridgeData.maxSlippage = uint32(bytes4(_data[40:44]));\n\n return (bridgeData, cBridgeData);\n }\n\n /// @notice Encodes calldata for startBridgeTokensViaCBridgeERC20Packed\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param sendingAssetId Address of the source asset to bridge\n /// @param minAmount Amount of the source asset to bridge\n /// @param nonce A number input to guarantee uniqueness of transferId\n /// @param maxSlippage Destination swap minimal accepted amount\n function encode_startBridgeTokensViaCBridgeERC20Packed(\n bytes32 transactionId,\n address receiver,\n uint64 destinationChainId,\n address sendingAssetId,\n uint256 minAmount,\n uint64 nonce,\n uint32 maxSlippage\n ) external pure returns (bytes memory) {\n require(\n destinationChainId <= type(uint32).max,\n \"destinationChainId value passed too big to fit in uint32\"\n );\n require(\n minAmount <= type(uint128).max,\n \"amount value passed too big to fit in uint128\"\n );\n require(\n nonce <= type(uint32).max,\n \"nonce value passed too big to fit in uint32\"\n );\n\n return\n bytes.concat(\n CBridgeFacetPacked\n .startBridgeTokensViaCBridgeERC20Packed\n .selector,\n bytes8(transactionId),\n bytes20(receiver),\n bytes4(uint32(destinationChainId)),\n bytes20(sendingAssetId),\n bytes16(uint128(minAmount)),\n bytes4(uint32(nonce)),\n bytes4(maxSlippage)\n );\n }\n\n function decode_startBridgeTokensViaCBridgeERC20Packed(\n bytes calldata _data\n )\n external\n pure\n returns (BridgeData memory, CBridgeFacet.CBridgeData memory)\n {\n require(_data.length >= 80, \"data passed is not the correct length\");\n\n BridgeData memory bridgeData;\n CBridgeFacet.CBridgeData memory cBridgeData;\n\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\n bridgeData.receiver = address(bytes20(_data[12:32]));\n bridgeData.destinationChainId = uint64(uint32(bytes4(_data[32:36])));\n bridgeData.sendingAssetId = address(bytes20(_data[36:56]));\n bridgeData.minAmount = uint256(uint128(bytes16(_data[56:72])));\n cBridgeData.nonce = uint64(uint32(bytes4(_data[72:76])));\n cBridgeData.maxSlippage = uint32(bytes4(_data[76:80]));\n\n return (bridgeData, cBridgeData);\n }\n}\n" + }, + "src/Interfaces/ICBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ICBridge {\n /// @notice Send a cross-chain transfer via the liquidity pool-based bridge.\n /// @dev This function DOES NOT SUPPORT fee-on-transfer / rebasing tokens.\n /// @param _receiver The address of the receiver.\n /// @param _token The address of the token.\n /// @param _amount The amount of the transfer.\n /// @param _dstChainId The destination chain ID.\n /// @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\n /// @param _maxSlippage The max slippage accepted, given as percentage in point (pip).\n /// Eg. 5000 means 0.5%. Must be greater than minimalMaxSlippage.\n /// Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount\n /// or the transfer can be refunded.\n function send(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce,\n uint32 _maxSlippage\n ) external;\n\n /// @notice Send a cross-chain transfer via the liquidity pool-based bridge using the native token.\n /// @param _receiver The address of the receiver.\n /// @param _amount The amount of the transfer.\n /// @param _dstChainId The destination chain ID.\n /// @param _nonce A unique number. Can be timestamp in practice.\n /// @param _maxSlippage The max slippage accepted, given as percentage in point (pip).\n /// Eg. 5000 means 0.5%. Must be greater than minimalMaxSlippage.\n /// Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount\n /// or the transfer can be refunded.\n function sendNative(\n address _receiver,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce,\n uint32 _maxSlippage\n ) external payable;\n}\n" + }, + "src/Facets/CBridgeFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { LibAccess } from \"../Libraries/LibAccess.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { ICBridge } from \"../Interfaces/ICBridge.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { ContractCallNotAllowed, ExternalCallFailed } from \"../Errors/GenericErrors.sol\";\n\n/// @title CBridge Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through CBridge\n/// @custom:version 1.0.0\ncontract CBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n /// @notice The contract address of the cbridge on the source chain.\n ICBridge private immutable cBridge;\n\n /// Types ///\n\n /// @param maxSlippage The max slippage accepted, given as percentage in point (pip).\n /// @param nonce A number input to guarantee uniqueness of transferId.\n /// Can be timestamp in practice.\n struct CBridgeData {\n uint32 maxSlippage;\n uint64 nonce;\n }\n\n /// Events ///\n event CBridgeRefund(\n address indexed _assetAddress,\n address indexed _to,\n uint256 amount\n );\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _cBridge The contract address of the cbridge on the source chain.\n constructor(ICBridge _cBridge) {\n cBridge = _cBridge;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via CBridge\n /// @param _bridgeData the core information needed for bridging\n /// @param _cBridgeData data specific to CBridge\n function startBridgeTokensViaCBridge(\n ILiFi.BridgeData memory _bridgeData,\n CBridgeData calldata _cBridgeData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData, _cBridgeData);\n }\n\n /// @notice Performs a swap before bridging via CBridge\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _cBridgeData data specific to CBridge\n function swapAndStartBridgeTokensViaCBridge(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n CBridgeData calldata _cBridgeData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n _startBridge(_bridgeData, _cBridgeData);\n }\n\n /// @notice Triggers a cBridge refund with calldata produced by cBridge API\n /// @param _callTo The address to execute the calldata on\n /// @param _callData The data to execute\n /// @param _assetAddress Asset to be withdrawn\n /// @param _to Address to withdraw to\n /// @param _amount Amount of asset to withdraw\n function triggerRefund(\n address payable _callTo,\n bytes calldata _callData,\n address _assetAddress,\n address _to,\n uint256 _amount\n ) external {\n if (msg.sender != LibDiamond.contractOwner()) {\n LibAccess.enforceAccessControl();\n }\n\n // make sure that callTo address is either of the cBridge addresses\n if (address(cBridge) != _callTo) {\n revert ContractCallNotAllowed();\n }\n\n // call contract\n bool success;\n (success, ) = _callTo.call(_callData);\n if (!success) {\n revert ExternalCallFailed();\n }\n\n // forward funds to _to address and emit event\n address sendTo = (LibUtil.isZeroAddress(_to)) ? msg.sender : _to;\n LibAsset.transferAsset(_assetAddress, payable(sendTo), _amount);\n emit CBridgeRefund(_assetAddress, sendTo, _amount);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via CBridge\n /// @param _bridgeData the core information needed for bridging\n /// @param _cBridgeData data specific to CBridge\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n CBridgeData calldata _cBridgeData\n ) private {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n cBridge.sendNative{ value: _bridgeData.minAmount }(\n _bridgeData.receiver,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _cBridgeData.nonce,\n _cBridgeData.maxSlippage\n );\n } else {\n // Give CBridge approval to bridge tokens\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(cBridge),\n _bridgeData.minAmount\n );\n // solhint-disable check-send-result\n cBridge.send(\n _bridgeData.receiver,\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _cBridgeData.nonce,\n _cBridgeData.maxSlippage\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "lib/solmate/src/utils/SafeTransferLib.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20} from \"../tokens/ERC20.sol\";\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n /*//////////////////////////////////////////////////////////////\n ETH OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferETH(address to, uint256 amount) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Transfer the ETH and store if it succeeded or not.\n success := call(gas(), to, amount, 0, 0, 0, 0)\n }\n\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferFrom(\n ERC20 token,\n address from,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), from) // Append the \"from\" argument.\n mstore(add(freeMemoryPointer, 36), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 68), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FROM_FAILED\");\n }\n\n function safeTransfer(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FAILED\");\n }\n\n function safeApprove(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"APPROVE_FAILED\");\n }\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Helpers/TransferrableOwnership.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IERC173 } from \"../Interfaces/IERC173.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\n\ncontract TransferrableOwnership is IERC173 {\n address public owner;\n address public pendingOwner;\n\n /// Errors ///\n error UnAuthorized();\n error NoNullOwner();\n error NewOwnerMustNotBeSelf();\n error NoPendingOwnershipTransfer();\n error NotPendingOwner();\n\n /// Events ///\n event OwnershipTransferRequested(\n address indexed _from,\n address indexed _to\n );\n\n constructor(address initialOwner) {\n owner = initialOwner;\n }\n\n modifier onlyOwner() {\n if (msg.sender != owner) revert UnAuthorized();\n _;\n }\n\n /// @notice Initiates transfer of ownership to a new address\n /// @param _newOwner the address to transfer ownership to\n function transferOwnership(address _newOwner) external onlyOwner {\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\n pendingOwner = _newOwner;\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\n }\n\n /// @notice Cancel transfer of ownership\n function cancelOwnershipTransfer() external onlyOwner {\n if (pendingOwner == LibAsset.NULL_ADDRESS)\n revert NoPendingOwnershipTransfer();\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\n function confirmOwnershipTransfer() external {\n address _pendingOwner = pendingOwner;\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n}\n" + }, + "src/Libraries/LibAccess.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { CannotAuthoriseSelf, UnAuthorized } from \"../Errors/GenericErrors.sol\";\n\n/// @title Access Library\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for managing method level access control\nlibrary LibAccess {\n /// Types ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.access.management\");\n\n /// Storage ///\n struct AccessStorage {\n mapping(bytes4 => mapping(address => bool)) execAccess;\n }\n\n /// Events ///\n event AccessGranted(address indexed account, bytes4 indexed method);\n event AccessRevoked(address indexed account, bytes4 indexed method);\n\n /// @dev Fetch local storage\n function accessStorage()\n internal\n pure\n returns (AccessStorage storage accStor)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n accStor.slot := position\n }\n }\n\n /// @notice Gives an address permission to execute a method\n /// @param selector The method selector to execute\n /// @param executor The address to grant permission to\n function addAccess(bytes4 selector, address executor) internal {\n if (executor == address(this)) {\n revert CannotAuthoriseSelf();\n }\n AccessStorage storage accStor = accessStorage();\n accStor.execAccess[selector][executor] = true;\n emit AccessGranted(executor, selector);\n }\n\n /// @notice Revokes permission to execute a method\n /// @param selector The method selector to execute\n /// @param executor The address to revoke permission from\n function removeAccess(bytes4 selector, address executor) internal {\n AccessStorage storage accStor = accessStorage();\n accStor.execAccess[selector][executor] = false;\n emit AccessRevoked(executor, selector);\n }\n\n /// @notice Enforces access control by reverting if `msg.sender`\n /// has not been given permission to execute `msg.sig`\n function enforceAccessControl() internal view {\n AccessStorage storage accStor = accessStorage();\n if (accStor.execAccess[msg.sig][msg.sender] != true)\n revert UnAuthorized();\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "lib/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\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 ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + }, + "src/Interfaces/IERC173.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\n/// @title ERC-173 Contract Ownership Standard\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\n/* is ERC165 */\ninterface IERC173 {\n /// @dev This emits when ownership of a contract changes.\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n /// @notice Get the address of the owner\n /// @return owner_ The address of the owner.\n function owner() external view returns (address owner_);\n\n /// @notice Set the address of the new owner of the contract\n /// @dev Set _newOwner to address(0) to renounce any ownership.\n /// @param _newOwner The address of the new owner of the contract\n function transferOwnership(address _newOwner) external;\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.3 + Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... |AllBridgeFacet +0xc0c42d148241c5b5bb38e974d40fc9087f7f9ecd +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/AllBridgeFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IAllBridge } from \\\"../Interfaces/IAllBridge.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { SwapperV2 } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\n/// @title Allbridge Facet\\n/// @author Li.Finance (https://li.finance)\\n/// @notice Provides functionality for bridging through AllBridge\\n/// @custom:version 2.0.0\\ncontract AllBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// @notice The contract address of the AllBridge router on the source chain.\\n IAllBridge private immutable allBridge;\\n\\n /// @notice The struct for the AllBridge data.\\n /// @param fees The amount of token to pay the messenger and the bridge\\n /// @param recipient The address of the token receiver after bridging.\\n /// @param destinationChainId The destination chain id.\\n /// @param receiveToken The token to receive on the destination chain.\\n /// @param nonce A random nonce to associate with the tx.\\n /// @param messenger The messenger protocol enum\\n /// @param payFeeWithSendingAsset Whether to pay the relayer fee with the sending asset or not\\n struct AllBridgeData {\\n uint256 fees;\\n bytes32 recipient;\\n uint256 destinationChainId;\\n bytes32 receiveToken;\\n uint256 nonce;\\n IAllBridge.MessengerProtocol messenger;\\n bool payFeeWithSendingAsset;\\n }\\n\\n /// @notice Initializes the AllBridge contract\\n /// @param _allBridge The address of the AllBridge contract\\n constructor(IAllBridge _allBridge) {\\n allBridge = _allBridge;\\n }\\n\\n /// @notice Bridge tokens to another chain via AllBridge\\n /// @param _bridgeData The bridge data struct\\n function startBridgeTokensViaAllBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n AllBridgeData calldata _allBridgeData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n validateBridgeData(_bridgeData)\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData, _allBridgeData);\\n }\\n\\n /// @notice Bridge tokens to another chain via AllBridge\\n /// @param _bridgeData The bridge data struct\\n /// @param _swapData The swap data struct\\n /// @param _allBridgeData The AllBridge data struct\\n function swapAndStartBridgeTokensViaAllBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n AllBridgeData calldata _allBridgeData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n _startBridge(_bridgeData, _allBridgeData);\\n }\\n\\n /// @notice Bridge tokens to another chain via AllBridge\\n /// @param _bridgeData The bridge data struct\\n /// @param _allBridgeData The allBridge data struct for AllBridge specicific data\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n AllBridgeData calldata _allBridgeData\\n ) internal {\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(allBridge),\\n _bridgeData.minAmount\\n );\\n\\n if (_allBridgeData.payFeeWithSendingAsset) {\\n allBridge.swapAndBridge(\\n bytes32(uint256(uint160(_bridgeData.sendingAssetId))),\\n _bridgeData.minAmount,\\n _allBridgeData.recipient,\\n _allBridgeData.destinationChainId,\\n _allBridgeData.receiveToken,\\n _allBridgeData.nonce,\\n _allBridgeData.messenger,\\n _allBridgeData.fees\\n );\\n } else {\\n allBridge.swapAndBridge{ value: _allBridgeData.fees }(\\n bytes32(uint256(uint160(_bridgeData.sendingAssetId))),\\n _bridgeData.minAmount,\\n _allBridgeData.recipient,\\n _allBridgeData.destinationChainId,\\n _allBridgeData.receiveToken,\\n _allBridgeData.nonce,\\n _allBridgeData.messenger,\\n 0\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IAllBridge.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\n/// @title AllBridge Interface\\ninterface IAllBridge {\\n /// @dev AllBridge Messenger Protocol Enum\\n enum MessengerProtocol {\\n None,\\n Allbridge,\\n Wormhole,\\n LayerZero\\n }\\n\\n function pools(bytes32 addr) external returns (address);\\n\\n function swapAndBridge(\\n bytes32 token,\\n uint256 amount,\\n bytes32 recipient,\\n uint256 destinationChainId,\\n bytes32 receiveToken,\\n uint256 nonce,\\n MessengerProtocol messenger,\\n uint256 feeTokenAmount\\n ) external payable;\\n\\n function getTransactionCost(\\n uint256 chainId\\n ) external view returns (uint256);\\n\\n function getMessageCost(\\n uint256 chainId,\\n MessengerProtocol protocol\\n ) external view returns (uint256);\\n\\n function getBridgingCostInTokens(\\n uint256 destinationChainId,\\n MessengerProtocol messenger,\\n address tokenAddress\\n ) external view returns (uint256);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IAllBridge\",\"name\":\"_allBridge\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"fees\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"receiveToken\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"enum IAllBridge.MessengerProtocol\",\"name\":\"messenger\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"payFeeWithSendingAsset\",\"type\":\"bool\"}],\"internalType\":\"struct AllBridgeFacet.AllBridgeData\",\"name\":\"_allBridgeData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaAllBridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"fees\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"recipient\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"receiveToken\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"enum IAllBridge.MessengerProtocol\",\"name\":\"messenger\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"payFeeWithSendingAsset\",\"type\":\"bool\"}],\"internalType\":\"struct AllBridgeFacet.AllBridgeData\",\"name\":\"_allBridgeData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaAllBridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "AllBridgeFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "000000000000000000000000609c690e8f7d68a59885c9132e812eebdaaf0c9e", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/AllBridgeFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IAllBridge } from \"../Interfaces/IAllBridge.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { SwapperV2 } from \"../Helpers/SwapperV2.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\n/// @title Allbridge Facet\n/// @author Li.Finance (https://li.finance)\n/// @notice Provides functionality for bridging through AllBridge\n/// @custom:version 2.0.0\ncontract AllBridgeFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// @notice The contract address of the AllBridge router on the source chain.\n IAllBridge private immutable allBridge;\n\n /// @notice The struct for the AllBridge data.\n /// @param fees The amount of token to pay the messenger and the bridge\n /// @param recipient The address of the token receiver after bridging.\n /// @param destinationChainId The destination chain id.\n /// @param receiveToken The token to receive on the destination chain.\n /// @param nonce A random nonce to associate with the tx.\n /// @param messenger The messenger protocol enum\n /// @param payFeeWithSendingAsset Whether to pay the relayer fee with the sending asset or not\n struct AllBridgeData {\n uint256 fees;\n bytes32 recipient;\n uint256 destinationChainId;\n bytes32 receiveToken;\n uint256 nonce;\n IAllBridge.MessengerProtocol messenger;\n bool payFeeWithSendingAsset;\n }\n\n /// @notice Initializes the AllBridge contract\n /// @param _allBridge The address of the AllBridge contract\n constructor(IAllBridge _allBridge) {\n allBridge = _allBridge;\n }\n\n /// @notice Bridge tokens to another chain via AllBridge\n /// @param _bridgeData The bridge data struct\n function startBridgeTokensViaAllBridge(\n ILiFi.BridgeData memory _bridgeData,\n AllBridgeData calldata _allBridgeData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n validateBridgeData(_bridgeData)\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData, _allBridgeData);\n }\n\n /// @notice Bridge tokens to another chain via AllBridge\n /// @param _bridgeData The bridge data struct\n /// @param _swapData The swap data struct\n /// @param _allBridgeData The AllBridge data struct\n function swapAndStartBridgeTokensViaAllBridge(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n AllBridgeData calldata _allBridgeData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n _startBridge(_bridgeData, _allBridgeData);\n }\n\n /// @notice Bridge tokens to another chain via AllBridge\n /// @param _bridgeData The bridge data struct\n /// @param _allBridgeData The allBridge data struct for AllBridge specicific data\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n AllBridgeData calldata _allBridgeData\n ) internal {\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(allBridge),\n _bridgeData.minAmount\n );\n\n if (_allBridgeData.payFeeWithSendingAsset) {\n allBridge.swapAndBridge(\n bytes32(uint256(uint160(_bridgeData.sendingAssetId))),\n _bridgeData.minAmount,\n _allBridgeData.recipient,\n _allBridgeData.destinationChainId,\n _allBridgeData.receiveToken,\n _allBridgeData.nonce,\n _allBridgeData.messenger,\n _allBridgeData.fees\n );\n } else {\n allBridge.swapAndBridge{ value: _allBridgeData.fees }(\n bytes32(uint256(uint160(_bridgeData.sendingAssetId))),\n _bridgeData.minAmount,\n _allBridgeData.recipient,\n _allBridgeData.destinationChainId,\n _allBridgeData.receiveToken,\n _allBridgeData.nonce,\n _allBridgeData.messenger,\n 0\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IAllBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\n/// @title AllBridge Interface\ninterface IAllBridge {\n /// @dev AllBridge Messenger Protocol Enum\n enum MessengerProtocol {\n None,\n Allbridge,\n Wormhole,\n LayerZero\n }\n\n function pools(bytes32 addr) external returns (address);\n\n function swapAndBridge(\n bytes32 token,\n uint256 amount,\n bytes32 recipient,\n uint256 destinationChainId,\n bytes32 receiveToken,\n uint256 nonce,\n MessengerProtocol messenger,\n uint256 feeTokenAmount\n ) external payable;\n\n function getTransactionCost(\n uint256 chainId\n ) external view returns (uint256);\n\n function getMessageCost(\n uint256 chainId,\n MessengerProtocol protocol\n ) external view returns (uint256);\n\n function getBridgingCostInTokens(\n uint256 destinationChainId,\n MessengerProtocol messenger,\n address tokenAddress\n ) external view returns (uint256);\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +2.0.0 + Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \HopFacetPacked +0x6ef81a18e1e432c289dc0d1a670b78e8bbf9aa35 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/HopFacetPacked.sol\": {\r\n \"content\": \"// // SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IHopBridge, IL2AmmWrapper, ISwap } from \\\"../Interfaces/IHopBridge.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { ERC20, SafeTransferLib } from \\\"solmate/utils/SafeTransferLib.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { TransferrableOwnership } from \\\"../Helpers/TransferrableOwnership.sol\\\";\\nimport { HopFacetOptimized } from \\\"lifi/Facets/HopFacetOptimized.sol\\\";\\nimport { WETH } from \\\"solmate/tokens/WETH.sol\\\";\\n\\n/// @title Hop Facet (Optimized for Rollups)\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Hop\\n/// @custom:version 1.0.6\\ncontract HopFacetPacked is ILiFi, TransferrableOwnership {\\n using SafeTransferLib for ERC20;\\n\\n /// Storage ///\\n\\n address public immutable nativeBridge;\\n address public immutable nativeL2CanonicalToken;\\n address public immutable nativeHToken;\\n address public immutable nativeExchangeAddress;\\n\\n /// Errors ///\\n\\n error Invalid();\\n\\n /// Events ///\\n\\n event LiFiHopTransfer(bytes8 _transactionId);\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _owner The contract owner to approve tokens.\\n /// @param _wrapper The address of Hop L2_AmmWrapper for native asset.\\n constructor(\\n address _owner,\\n address _wrapper\\n ) TransferrableOwnership(_owner) {\\n bool wrapperIsSet = _wrapper != address(0);\\n\\n if (block.chainid == 1 && wrapperIsSet) {\\n revert Invalid();\\n }\\n\\n nativeL2CanonicalToken = wrapperIsSet\\n ? IL2AmmWrapper(_wrapper).l2CanonicalToken()\\n : address(0);\\n nativeHToken = wrapperIsSet\\n ? IL2AmmWrapper(_wrapper).hToken()\\n : address(0);\\n nativeExchangeAddress = wrapperIsSet\\n ? IL2AmmWrapper(_wrapper).exchangeAddress()\\n : address(0);\\n nativeBridge = wrapperIsSet\\n ? IL2AmmWrapper(_wrapper).bridge()\\n : address(0);\\n }\\n\\n /// External Methods ///\\n\\n /// @dev Only meant to be called outside of the context of the diamond\\n /// @notice Sets approval for the Hop Bridge to spend the specified token\\n /// @param bridges The Hop Bridges to approve\\n /// @param tokensToApprove The tokens to approve to approve to the Hop Bridges\\n function setApprovalForHopBridges(\\n address[] calldata bridges,\\n address[] calldata tokensToApprove\\n ) external onlyOwner {\\n uint256 numBridges = bridges.length;\\n\\n for (uint256 i; i < numBridges; i++) {\\n // Give Hop approval to bridge tokens\\n LibAsset.maxApproveERC20(\\n IERC20(tokensToApprove[i]),\\n address(bridges[i]),\\n type(uint256).max\\n );\\n }\\n }\\n\\n /// @notice Bridges Native tokens via Hop Protocol from L2\\n /// No params, all data will be extracted from manually encoded callData\\n function startBridgeTokensViaHopL2NativePacked() external payable {\\n // first 4 bytes are function signature\\n // transactionId: bytes8(msg.data[4:12]),\\n // receiver: address(bytes20(msg.data[12:32])),\\n // destinationChainId: uint256(uint32(bytes4(msg.data[32:36]))),\\n // bonderFee: uint256(uint128(bytes16(msg.data[36:52]))),\\n // amountOutMin: uint256(uint128(bytes16(msg.data[52:68])))\\n // => total calldata length required: 68\\n\\n uint256 destinationChainId = uint256(uint32(bytes4(msg.data[32:36])));\\n uint256 amountOutMin = uint256(uint128(bytes16(msg.data[52:68])));\\n bool toL1 = destinationChainId == 1;\\n\\n // Wrap ETH\\n WETH(payable(nativeL2CanonicalToken)).deposit{ value: msg.value }();\\n\\n // Exchange WETH for hToken\\n uint256 swapAmount = ISwap(nativeExchangeAddress).swap(\\n 0,\\n 1,\\n msg.value,\\n amountOutMin,\\n block.timestamp\\n );\\n\\n // Bridge assets\\n // solhint-disable-next-line check-send-result\\n IHopBridge(nativeBridge).send(\\n destinationChainId,\\n address(bytes20(msg.data[12:32])), // receiver\\n swapAmount,\\n uint256(uint128(bytes16(msg.data[36:52]))), // bonderFee\\n toL1 ? 0 : amountOutMin,\\n toL1 ? 0 : block.timestamp + 7 * 24 * 60 * 60\\n );\\n\\n emit LiFiHopTransfer(\\n bytes8(msg.data[4:12]) // transactionId\\n );\\n }\\n\\n /// @notice Bridges Native tokens via Hop Protocol from L2\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param bonderFee Fees payed to hop bonder\\n /// @param amountOutMin Source swap minimal accepted amount\\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\\n /// @param destinationDeadline Destination swap maximal time\\n /// @param hopBridge Address of the Hop L2_AmmWrapper\\n function startBridgeTokensViaHopL2NativeMin(\\n bytes8 transactionId,\\n address receiver,\\n uint256 destinationChainId,\\n uint256 bonderFee,\\n uint256 amountOutMin,\\n uint256 destinationAmountOutMin,\\n uint256 destinationDeadline,\\n address hopBridge\\n ) external payable {\\n // Bridge assets\\n IHopBridge(hopBridge).swapAndSend{ value: msg.value }(\\n destinationChainId,\\n receiver,\\n msg.value,\\n bonderFee,\\n amountOutMin,\\n block.timestamp,\\n destinationAmountOutMin,\\n destinationDeadline\\n );\\n\\n emit LiFiHopTransfer(transactionId);\\n }\\n\\n /// @notice Bridges Native tokens via Hop Protocol from L2\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param bonderFee Fees payed to hop bonder\\n /// @param amountOutMin Source swap minimal accepted amount\\n function encode_startBridgeTokensViaHopL2NativePacked(\\n bytes8 transactionId,\\n address receiver,\\n uint256 destinationChainId,\\n uint256 bonderFee,\\n uint256 amountOutMin\\n ) external pure returns (bytes memory) {\\n require(\\n destinationChainId <= type(uint32).max,\\n \\\"destinationChainId value passed too big to fit in uint32\\\"\\n );\\n require(\\n bonderFee <= type(uint128).max,\\n \\\"bonderFee value passed too big to fit in uint128\\\"\\n );\\n require(\\n amountOutMin <= type(uint128).max,\\n \\\"amountOutMin value passed too big to fit in uint128\\\"\\n );\\n\\n return\\n bytes.concat(\\n HopFacetPacked.startBridgeTokensViaHopL2NativePacked.selector,\\n bytes8(transactionId),\\n bytes20(receiver),\\n bytes4(uint32(destinationChainId)),\\n bytes16(uint128(bonderFee)),\\n bytes16(uint128(amountOutMin))\\n );\\n }\\n\\n /// @notice Decodes calldata for startBridgeTokensViaHopL2NativePacked\\n /// @param _data the calldata to decode\\n function decode_startBridgeTokensViaHopL2NativePacked(\\n bytes calldata _data\\n )\\n external\\n pure\\n returns (BridgeData memory, HopFacetOptimized.HopData memory)\\n {\\n require(\\n _data.length >= 68,\\n \\\"data passed in is not the correct length\\\"\\n );\\n\\n BridgeData memory bridgeData;\\n HopFacetOptimized.HopData memory hopData;\\n\\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\\n bridgeData.receiver = address(bytes20(_data[12:32]));\\n bridgeData.destinationChainId = uint256(uint32(bytes4(_data[32:36])));\\n hopData.bonderFee = uint256(uint128(bytes16(_data[36:52])));\\n hopData.amountOutMin = uint256(uint128(bytes16(_data[52:68])));\\n\\n return (bridgeData, hopData);\\n }\\n\\n /// @notice Bridges ERC20 tokens via Hop Protocol from L2\\n /// No params, all data will be extracted from manually encoded callData\\n function startBridgeTokensViaHopL2ERC20Packed() external {\\n // first 4 bytes are function signature\\n // transactionId: bytes8(msg.data[4:12]),\\n // receiver: address(bytes20(msg.data[12:32])),\\n // destinationChainId: uint256(uint32(bytes4(msg.data[32:36]))),\\n // sendingAssetId: address(bytes20(msg.data[36:56])),\\n // amount: uint256(uint128(bytes16(msg.data[56:72]))),\\n // bonderFee: uint256(uint128(bytes16(msg.data[72:88]))),\\n // amountOutMin: uint256(uint128(bytes16(msg.data[88:104]))),\\n // destinationAmountOutMin: uint256(uint128(bytes16(msg.data[104:120]))),\\n // destinationDeadline: uint256(uint32(bytes4(msg.data[120:124]))),\\n // wrapper: address(bytes20(msg.data[124:144]))\\n // => total calldata length required: 144\\n\\n uint256 destinationChainId = uint256(uint32(bytes4(msg.data[32:36])));\\n uint256 amount = uint256(uint128(bytes16(msg.data[56:72])));\\n uint256 amountOutMin = uint256(uint128(bytes16(msg.data[88:104])));\\n bool toL1 = destinationChainId == 1;\\n\\n IL2AmmWrapper wrapper = IL2AmmWrapper(\\n address(bytes20(msg.data[124:144]))\\n );\\n\\n // Deposit assets\\n ERC20(address(bytes20(msg.data[36:56]))).safeTransferFrom(\\n msg.sender,\\n address(this),\\n amount\\n );\\n\\n // Exchange sending asset to hToken\\n uint256 swapAmount = ISwap(wrapper.exchangeAddress()).swap(\\n 0,\\n 1,\\n amount,\\n amountOutMin,\\n block.timestamp\\n );\\n\\n // Bridge assets\\n // solhint-disable-next-line check-send-result\\n IHopBridge(wrapper.bridge()).send(\\n destinationChainId,\\n address(bytes20(msg.data[12:32])),\\n swapAmount,\\n uint256(uint128(bytes16(msg.data[72:88]))),\\n toL1 ? 0 : uint256(uint128(bytes16(msg.data[104:120]))),\\n toL1 ? 0 : uint256(uint32(bytes4(msg.data[120:124])))\\n );\\n\\n emit LiFiHopTransfer(bytes8(msg.data[4:12]));\\n }\\n\\n /// @notice Bridges ERC20 tokens via Hop Protocol from L2\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param sendingAssetId Address of the source asset to bridge\\n /// @param minAmount Amount of the source asset to bridge\\n /// @param bonderFee Fees payed to hop bonder\\n /// @param amountOutMin Source swap minimal accepted amount\\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\\n /// @param destinationDeadline Destination swap maximal time\\n /// @param hopBridge Address of the Hop L2_AmmWrapper\\n function startBridgeTokensViaHopL2ERC20Min(\\n bytes8 transactionId,\\n address receiver,\\n uint256 destinationChainId,\\n address sendingAssetId,\\n uint256 minAmount,\\n uint256 bonderFee,\\n uint256 amountOutMin,\\n uint256 destinationAmountOutMin,\\n uint256 destinationDeadline,\\n address hopBridge\\n ) external {\\n // Deposit assets\\n ERC20(sendingAssetId).safeTransferFrom(\\n msg.sender,\\n address(this),\\n minAmount\\n );\\n\\n // Bridge assets\\n IHopBridge(hopBridge).swapAndSend(\\n destinationChainId,\\n receiver,\\n minAmount,\\n bonderFee,\\n amountOutMin,\\n block.timestamp,\\n destinationAmountOutMin,\\n destinationDeadline\\n );\\n\\n emit LiFiHopTransfer(transactionId);\\n }\\n\\n /// @notice Bridges ERC20 tokens via Hop Protocol from L2\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param sendingAssetId Address of the source asset to bridge\\n /// @param minAmount Amount of the source asset to bridge\\n /// @param bonderFee Fees payed to hop bonder\\n /// @param amountOutMin Source swap minimal accepted amount\\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\\n /// @param destinationDeadline Destination swap maximal time\\n /// @param wrapper Address of the Hop L2_AmmWrapper\\n function encode_startBridgeTokensViaHopL2ERC20Packed(\\n bytes32 transactionId,\\n address receiver,\\n uint256 destinationChainId,\\n address sendingAssetId,\\n uint256 minAmount,\\n uint256 bonderFee,\\n uint256 amountOutMin,\\n uint256 destinationAmountOutMin,\\n uint256 destinationDeadline,\\n address wrapper\\n ) external pure returns (bytes memory) {\\n require(\\n destinationChainId <= type(uint32).max,\\n \\\"destinationChainId value passed too big to fit in uint32\\\"\\n );\\n require(\\n minAmount <= type(uint128).max,\\n \\\"amount value passed too big to fit in uint128\\\"\\n );\\n require(\\n bonderFee <= type(uint128).max,\\n \\\"bonderFee value passed too big to fit in uint128\\\"\\n );\\n require(\\n amountOutMin <= type(uint128).max,\\n \\\"amountOutMin value passed too big to fit in uint128\\\"\\n );\\n require(\\n destinationAmountOutMin <= type(uint128).max,\\n \\\"destinationAmountOutMin value passed too big to fit in uint128\\\"\\n );\\n require(\\n destinationDeadline <= type(uint32).max,\\n \\\"destinationDeadline value passed too big to fit in uint32\\\"\\n );\\n\\n return\\n bytes.concat(\\n HopFacetPacked.startBridgeTokensViaHopL2ERC20Packed.selector,\\n bytes8(transactionId),\\n bytes20(receiver),\\n bytes4(uint32(destinationChainId)),\\n bytes20(sendingAssetId),\\n bytes16(uint128(minAmount)),\\n bytes16(uint128(bonderFee)),\\n bytes16(uint128(amountOutMin)),\\n bytes16(uint128(destinationAmountOutMin)),\\n bytes4(uint32(destinationDeadline)),\\n bytes20(wrapper)\\n );\\n }\\n\\n /// @notice Decodes calldata for startBridgeTokensViaHopL2ERC20Packed\\n /// @param _data the calldata to decode\\n function decode_startBridgeTokensViaHopL2ERC20Packed(\\n bytes calldata _data\\n )\\n external\\n pure\\n returns (BridgeData memory, HopFacetOptimized.HopData memory)\\n {\\n require(\\n _data.length >= 144,\\n \\\"data passed in is not the correct length\\\"\\n );\\n\\n BridgeData memory bridgeData;\\n HopFacetOptimized.HopData memory hopData;\\n\\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\\n bridgeData.receiver = address(bytes20(_data[12:32]));\\n bridgeData.destinationChainId = uint256(uint32(bytes4(_data[32:36])));\\n bridgeData.sendingAssetId = address(bytes20(_data[36:56]));\\n bridgeData.minAmount = uint256(uint128(bytes16(_data[56:72])));\\n hopData.bonderFee = uint256(uint128(bytes16(_data[72:88])));\\n hopData.amountOutMin = uint256(uint128(bytes16(_data[88:104])));\\n hopData.destinationAmountOutMin = uint256(\\n uint128(bytes16(_data[104:120]))\\n );\\n hopData.destinationDeadline = uint256(uint32(bytes4(_data[120:124])));\\n hopData.hopBridge = IHopBridge(address(bytes20(_data[124:144])));\\n\\n return (bridgeData, hopData);\\n }\\n\\n /// @notice Bridges Native tokens via Hop Protocol from L1\\n /// No params, all data will be extracted from manually encoded callData\\n function startBridgeTokensViaHopL1NativePacked() external payable {\\n // first 4 bytes are function signature\\n // transactionId: bytes8(msg.data[4:12]),\\n // receiver: address(bytes20(msg.data[12:32])),\\n // destinationChainId: uint256(uint32(bytes4(msg.data[32:36]))),\\n // destinationAmountOutMin: uint256(uint128(bytes16(msg.data[36:52]))),\\n // relayer: address(bytes20(msg.data[52:72])),\\n // relayerFee: uint256(uint128(bytes16(msg.data[72:88]))),\\n // hopBridge: address(bytes20(msg.data[88:108]))\\n // => total calldata length required: 108\\n\\n // Bridge assets\\n IHopBridge(address(bytes20(msg.data[88:108]))).sendToL2{\\n value: msg.value\\n }(\\n uint256(uint32(bytes4(msg.data[32:36]))),\\n address(bytes20(msg.data[12:32])),\\n msg.value,\\n uint256(uint128(bytes16(msg.data[36:52]))),\\n block.timestamp + 7 * 24 * 60 * 60,\\n address(bytes20(msg.data[52:72])),\\n uint256(uint128(bytes16(msg.data[72:88])))\\n );\\n\\n emit LiFiHopTransfer(bytes8(msg.data[4:12]));\\n }\\n\\n /// @notice Bridges Native tokens via Hop Protocol from L1\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\\n /// @param relayer needed for gas spikes\\n /// @param relayerFee needed for gas spikes\\n /// @param hopBridge Address of the Hop Bridge\\n function startBridgeTokensViaHopL1NativeMin(\\n bytes8 transactionId,\\n address receiver,\\n uint256 destinationChainId,\\n uint256 destinationAmountOutMin,\\n address relayer,\\n uint256 relayerFee,\\n address hopBridge\\n ) external payable {\\n // Bridge assets\\n IHopBridge(hopBridge).sendToL2{ value: msg.value }(\\n destinationChainId,\\n receiver,\\n msg.value,\\n destinationAmountOutMin,\\n block.timestamp + 7 * 24 * 60 * 60,\\n relayer,\\n relayerFee\\n );\\n\\n emit LiFiHopTransfer(transactionId);\\n }\\n\\n /// @notice Bridges Native tokens via Hop Protocol from L1\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\\n /// @param relayer needed for gas spikes\\n /// @param relayerFee needed for gas spikes\\n /// @param hopBridge Address of the Hop Bridge\\n function encode_startBridgeTokensViaHopL1NativePacked(\\n bytes8 transactionId,\\n address receiver,\\n uint256 destinationChainId,\\n uint256 destinationAmountOutMin,\\n address relayer,\\n uint256 relayerFee,\\n address hopBridge\\n ) external pure returns (bytes memory) {\\n require(\\n destinationChainId <= type(uint32).max,\\n \\\"destinationChainId value passed too big to fit in uint32\\\"\\n );\\n require(\\n destinationAmountOutMin <= type(uint128).max,\\n \\\"destinationAmountOutMin value passed too big to fit in uint128\\\"\\n );\\n require(\\n relayerFee <= type(uint128).max,\\n \\\"relayerFee value passed too big to fit in uint128\\\"\\n );\\n\\n return\\n bytes.concat(\\n HopFacetPacked.startBridgeTokensViaHopL1NativePacked.selector,\\n bytes8(transactionId),\\n bytes20(receiver),\\n bytes4(uint32(destinationChainId)),\\n bytes16(uint128(destinationAmountOutMin)),\\n bytes20(relayer),\\n bytes16(uint128(relayerFee)),\\n bytes20(hopBridge)\\n );\\n }\\n\\n /// @notice Decodes calldata for startBridgeTokensViaHopL1NativePacked\\n /// @param _data the calldata to decode\\n function decode_startBridgeTokensViaHopL1NativePacked(\\n bytes calldata _data\\n )\\n external\\n pure\\n returns (BridgeData memory, HopFacetOptimized.HopData memory)\\n {\\n require(\\n _data.length >= 108,\\n \\\"data passed in is not the correct length\\\"\\n );\\n\\n BridgeData memory bridgeData;\\n HopFacetOptimized.HopData memory hopData;\\n\\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\\n bridgeData.receiver = address(bytes20(_data[12:32]));\\n bridgeData.destinationChainId = uint256(uint32(bytes4(_data[32:36])));\\n hopData.destinationAmountOutMin = uint256(\\n uint128(bytes16(_data[36:52]))\\n );\\n // relayer = address(bytes20(_data[52:72]));\\n // relayerFee = uint256(uint128(bytes16(_data[72:88])));\\n hopData.hopBridge = IHopBridge(address(bytes20(_data[88:108])));\\n\\n return (bridgeData, hopData);\\n }\\n\\n /// @notice Bridges Native tokens via Hop Protocol from L1\\n /// No params, all data will be extracted from manually encoded callData\\n function startBridgeTokensViaHopL1ERC20Packed() external payable {\\n // first 4 bytes are function signature\\n // transactionId: bytes8(msg.data[4:12]),\\n // receiver: address(bytes20(msg.data[12:32])),\\n // destinationChainId: uint256(uint32(bytes4(msg.data[32:36]))),\\n // sendingAssetId: address(bytes20(msg.data[36:56])),\\n // amount: uint256(uint128(bytes16(msg.data[56:72]))),\\n // destinationAmountOutMin: uint256(uint128(bytes16(msg.data[72:88]))),\\n // relayer: address(bytes20(msg.data[88:108])),\\n // relayerFee: uint256(uint128(bytes16(msg.data[108:124]))),\\n // hopBridge: address(bytes20(msg.data[124:144]))\\n // => total calldata length required: 144\\n\\n uint256 amount = uint256(uint128(bytes16(msg.data[56:72])));\\n\\n // Deposit assets\\n ERC20(address(bytes20(msg.data[36:56]))).safeTransferFrom(\\n msg.sender,\\n address(this),\\n amount\\n );\\n\\n // Bridge assets\\n IHopBridge(address(bytes20(msg.data[124:144]))).sendToL2(\\n uint256(uint32(bytes4(msg.data[32:36]))),\\n address(bytes20(msg.data[12:32])),\\n amount,\\n uint256(uint128(bytes16(msg.data[72:88]))),\\n block.timestamp + 7 * 24 * 60 * 60,\\n address(bytes20(msg.data[88:108])),\\n uint256(uint128(bytes16(msg.data[108:124])))\\n );\\n\\n emit LiFiHopTransfer(bytes8(msg.data[4:12]));\\n }\\n\\n /// @notice Bridges ERC20 tokens via Hop Protocol from L1\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param sendingAssetId Address of the source asset to bridge\\n /// @param minAmount Amount of the source asset to bridge\\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\\n /// @param relayer needed for gas spikes\\n /// @param relayerFee needed for gas spikes\\n /// @param hopBridge Address of the Hop Bridge\\n function startBridgeTokensViaHopL1ERC20Min(\\n bytes8 transactionId,\\n address receiver,\\n uint256 destinationChainId,\\n address sendingAssetId,\\n uint256 minAmount,\\n uint256 destinationAmountOutMin,\\n address relayer,\\n uint256 relayerFee,\\n address hopBridge\\n ) external {\\n // Deposit assets\\n ERC20(sendingAssetId).safeTransferFrom(\\n msg.sender,\\n address(this),\\n minAmount\\n );\\n\\n // Bridge assets\\n IHopBridge(hopBridge).sendToL2(\\n destinationChainId,\\n receiver,\\n minAmount,\\n destinationAmountOutMin,\\n block.timestamp + 7 * 24 * 60 * 60,\\n relayer,\\n relayerFee\\n );\\n\\n emit LiFiHopTransfer(transactionId);\\n }\\n\\n /// @notice Bridges ERC20 tokens via Hop Protocol from L1\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param destinationChainId Receiving chain\\n /// @param sendingAssetId Address of the source asset to bridge\\n /// @param minAmount Amount of the source asset to bridge\\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\\n /// @param relayer needed for gas spikes\\n /// @param relayerFee needed for gas spikes\\n /// @param hopBridge Address of the Hop Bridge\\n function encode_startBridgeTokensViaHopL1ERC20Packed(\\n bytes8 transactionId,\\n address receiver,\\n uint256 destinationChainId,\\n address sendingAssetId,\\n uint256 minAmount,\\n uint256 destinationAmountOutMin,\\n address relayer,\\n uint256 relayerFee,\\n address hopBridge\\n ) external pure returns (bytes memory) {\\n require(\\n destinationChainId <= type(uint32).max,\\n \\\"destinationChainId value passed too big to fit in uint32\\\"\\n );\\n require(\\n minAmount <= type(uint128).max,\\n \\\"amount value passed too big to fit in uint128\\\"\\n );\\n require(\\n destinationAmountOutMin <= type(uint128).max,\\n \\\"destinationAmountOutMin value passed too big to fit in uint128\\\"\\n );\\n require(\\n relayerFee <= type(uint128).max,\\n \\\"relayerFee value passed too big to fit in uint128\\\"\\n );\\n\\n return\\n bytes.concat(\\n HopFacetPacked.startBridgeTokensViaHopL1ERC20Packed.selector,\\n bytes8(transactionId),\\n bytes20(receiver),\\n bytes4(uint32(destinationChainId)),\\n bytes20(sendingAssetId),\\n bytes16(uint128(minAmount)),\\n bytes16(uint128(destinationAmountOutMin)),\\n bytes20(relayer),\\n bytes16(uint128(relayerFee)),\\n bytes20(hopBridge)\\n );\\n }\\n\\n /// @notice Decodes calldata for startBridgeTokensViaHopL1ERC20Packed\\n /// @param _data the calldata to decode\\n function decode_startBridgeTokensViaHopL1ERC20Packed(\\n bytes calldata _data\\n )\\n external\\n pure\\n returns (BridgeData memory, HopFacetOptimized.HopData memory)\\n {\\n require(\\n _data.length >= 144,\\n \\\"data passed in is not the correct length\\\"\\n );\\n\\n BridgeData memory bridgeData;\\n HopFacetOptimized.HopData memory hopData;\\n\\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\\n bridgeData.receiver = address(bytes20(_data[12:32]));\\n bridgeData.destinationChainId = uint256(uint32(bytes4(_data[32:36])));\\n bridgeData.sendingAssetId = address(bytes20(_data[36:56]));\\n bridgeData.minAmount = uint256(uint128(bytes16(_data[56:72])));\\n hopData.destinationAmountOutMin = uint256(\\n uint128(bytes16(_data[72:88]))\\n );\\n // relayer = address(bytes20(_data[88:108]));\\n // relayerFee = uint256(uint128(bytes16(_data[108:124])));\\n hopData.hopBridge = IHopBridge(address(bytes20(_data[124:144])));\\n\\n return (bridgeData, hopData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IHopBridge.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IHopBridge {\\n function sendToL2(\\n uint256 chainId,\\n address recipient,\\n uint256 amount,\\n uint256 amountOutMin,\\n uint256 deadline,\\n address relayer,\\n uint256 relayerFee\\n ) external payable;\\n\\n function swapAndSend(\\n uint256 chainId,\\n address recipient,\\n uint256 amount,\\n uint256 bonderFee,\\n uint256 amountOutMin,\\n uint256 deadline,\\n uint256 destinationAmountOutMin,\\n uint256 destinationDeadline\\n ) external payable;\\n\\n function send(\\n uint256 chainId,\\n address recipient,\\n uint256 amount,\\n uint256 bonderFee,\\n uint256 amountOutMin,\\n uint256 deadline\\n ) external;\\n}\\n\\ninterface IL2AmmWrapper {\\n function bridge() external view returns (address);\\n\\n function l2CanonicalToken() external view returns (address);\\n\\n function hToken() external view returns (address);\\n\\n function exchangeAddress() external view returns (address);\\n}\\n\\ninterface ISwap {\\n function swap(\\n uint8 tokenIndexFrom,\\n uint8 tokenIndexTo,\\n uint256 dx,\\n uint256 minDy,\\n uint256 deadline\\n ) external returns (uint256);\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"lib/solmate/src/utils/SafeTransferLib.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\nimport {ERC20} from \\\"../tokens/ERC20.sol\\\";\\n\\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\\nlibrary SafeTransferLib {\\n /*//////////////////////////////////////////////////////////////\\n ETH OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferETH(address to, uint256 amount) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Transfer the ETH and store if it succeeded or not.\\n success := call(gas(), to, amount, 0, 0, 0, 0)\\n }\\n\\n require(success, \\\"ETH_TRANSFER_FAILED\\\");\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferFrom(\\n ERC20 token,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), from) // Append the \\\"from\\\" argument.\\n mstore(add(freeMemoryPointer, 36), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 68), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FROM_FAILED\\\");\\n }\\n\\n function safeTransfer(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FAILED\\\");\\n }\\n\\n function safeApprove(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"APPROVE_FAILED\\\");\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/TransferrableOwnership.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IERC173 } from \\\"../Interfaces/IERC173.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\n\\ncontract TransferrableOwnership is IERC173 {\\n address public owner;\\n address public pendingOwner;\\n\\n /// Errors ///\\n error UnAuthorized();\\n error NoNullOwner();\\n error NewOwnerMustNotBeSelf();\\n error NoPendingOwnershipTransfer();\\n error NotPendingOwner();\\n\\n /// Events ///\\n event OwnershipTransferRequested(\\n address indexed _from,\\n address indexed _to\\n );\\n\\n constructor(address initialOwner) {\\n owner = initialOwner;\\n }\\n\\n modifier onlyOwner() {\\n if (msg.sender != owner) revert UnAuthorized();\\n _;\\n }\\n\\n /// @notice Initiates transfer of ownership to a new address\\n /// @param _newOwner the address to transfer ownership to\\n function transferOwnership(address _newOwner) external onlyOwner {\\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\\n pendingOwner = _newOwner;\\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\\n }\\n\\n /// @notice Cancel transfer of ownership\\n function cancelOwnershipTransfer() external onlyOwner {\\n if (pendingOwner == LibAsset.NULL_ADDRESS)\\n revert NoPendingOwnershipTransfer();\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n\\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\\n function confirmOwnershipTransfer() external {\\n address _pendingOwner = pendingOwner;\\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\\n emit OwnershipTransferred(owner, _pendingOwner);\\n owner = _pendingOwner;\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n}\\n\"\r\n },\r\n \"src/Facets/HopFacetOptimized.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IHopBridge } from \\\"../Interfaces/IHopBridge.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\n\\n/// @title Hop Facet (Optimized)\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Hop\\n/// @custom:version 2.0.0\\ncontract HopFacetOptimized is ILiFi, SwapperV2 {\\n /// Types ///\\n\\n struct HopData {\\n uint256 bonderFee;\\n uint256 amountOutMin;\\n uint256 deadline;\\n uint256 destinationAmountOutMin;\\n uint256 destinationDeadline;\\n IHopBridge hopBridge;\\n address relayer;\\n uint256 relayerFee;\\n uint256 nativeFee;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Sets approval for the Hop Bridge to spend the specified token\\n /// @param bridges The Hop Bridges to approve\\n /// @param tokensToApprove The tokens to approve to approve to the Hop Bridges\\n function setApprovalForBridges(\\n address[] calldata bridges,\\n address[] calldata tokensToApprove\\n ) external {\\n LibDiamond.enforceIsContractOwner();\\n for (uint256 i; i < bridges.length; i++) {\\n // Give Hop approval to bridge tokens\\n LibAsset.maxApproveERC20(\\n IERC20(tokensToApprove[i]),\\n address(bridges[i]),\\n type(uint256).max\\n );\\n }\\n }\\n\\n /// @notice Bridges ERC20 tokens via Hop Protocol from L1\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _hopData data specific to Hop Protocol\\n function startBridgeTokensViaHopL1ERC20(\\n ILiFi.BridgeData calldata _bridgeData,\\n HopData calldata _hopData\\n ) external payable {\\n // Deposit assets\\n LibAsset.transferFromERC20(\\n _bridgeData.sendingAssetId,\\n msg.sender,\\n address(this),\\n _bridgeData.minAmount\\n );\\n // Bridge assets\\n _hopData.hopBridge.sendToL2{ value: _hopData.nativeFee }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline,\\n _hopData.relayer,\\n _hopData.relayerFee\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Bridges Native tokens via Hop Protocol from L1\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _hopData data specific to Hop Protocol\\n function startBridgeTokensViaHopL1Native(\\n ILiFi.BridgeData calldata _bridgeData,\\n HopData calldata _hopData\\n ) external payable {\\n // Bridge assets\\n _hopData.hopBridge.sendToL2{\\n value: _bridgeData.minAmount + _hopData.nativeFee\\n }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline,\\n _hopData.relayer,\\n _hopData.relayerFee\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging ERC20 tokens via Hop Protocol from L1\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _hopData data specific to Hop Protocol\\n function swapAndStartBridgeTokensViaHopL1ERC20(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n HopData calldata _hopData\\n ) external payable {\\n // Deposit and swap assets\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n _hopData.nativeFee\\n );\\n\\n // Bridge assets\\n _hopData.hopBridge.sendToL2{ value: _hopData.nativeFee }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline,\\n _hopData.relayer,\\n _hopData.relayerFee\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging Native tokens via Hop Protocol from L1\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _hopData data specific to Hop Protocol\\n function swapAndStartBridgeTokensViaHopL1Native(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n HopData calldata _hopData\\n ) external payable {\\n // Deposit and swap assets\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n _hopData.nativeFee\\n );\\n\\n // Bridge assets\\n _hopData.hopBridge.sendToL2{\\n value: _bridgeData.minAmount + _hopData.nativeFee\\n }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline,\\n _hopData.relayer,\\n _hopData.relayerFee\\n );\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Bridges ERC20 tokens via Hop Protocol from L2\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _hopData data specific to Hop Protocol\\n function startBridgeTokensViaHopL2ERC20(\\n ILiFi.BridgeData calldata _bridgeData,\\n HopData calldata _hopData\\n ) external {\\n // Deposit assets\\n LibAsset.transferFromERC20(\\n _bridgeData.sendingAssetId,\\n msg.sender,\\n address(this),\\n _bridgeData.minAmount\\n );\\n // Bridge assets\\n _hopData.hopBridge.swapAndSend(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.bonderFee,\\n _hopData.amountOutMin,\\n _hopData.deadline,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Bridges Native tokens via Hop Protocol from L2\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _hopData data specific to Hop Protocol\\n function startBridgeTokensViaHopL2Native(\\n ILiFi.BridgeData calldata _bridgeData,\\n HopData calldata _hopData\\n ) external payable {\\n // Bridge assets\\n _hopData.hopBridge.swapAndSend{ value: _bridgeData.minAmount }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.bonderFee,\\n _hopData.amountOutMin,\\n _hopData.deadline,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging ERC20 tokens via Hop Protocol from L2\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _hopData data specific to Hop Protocol\\n function swapAndStartBridgeTokensViaHopL2ERC20(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n HopData calldata _hopData\\n ) external payable {\\n // Deposit and swap assets\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n // Bridge assets\\n _hopData.hopBridge.swapAndSend(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.bonderFee,\\n _hopData.amountOutMin,\\n _hopData.deadline,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging Native tokens via Hop Protocol from L2\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _hopData data specific to Hop Protocol\\n function swapAndStartBridgeTokensViaHopL2Native(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n HopData calldata _hopData\\n ) external payable {\\n // Deposit and swap assets\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n // Bridge assets\\n _hopData.hopBridge.swapAndSend{ value: _bridgeData.minAmount }(\\n _bridgeData.destinationChainId,\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n _hopData.bonderFee,\\n _hopData.amountOutMin,\\n _hopData.deadline,\\n _hopData.destinationAmountOutMin,\\n _hopData.destinationDeadline\\n );\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"lib/solmate/src/tokens/WETH.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\nimport {ERC20} from \\\"./ERC20.sol\\\";\\n\\nimport {SafeTransferLib} from \\\"../utils/SafeTransferLib.sol\\\";\\n\\n/// @notice Minimalist and modern Wrapped Ether implementation.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/WETH.sol)\\n/// @author Inspired by WETH9 (https://github.com/dapphub/ds-weth/blob/master/src/weth9.sol)\\ncontract WETH is ERC20(\\\"Wrapped Ether\\\", \\\"WETH\\\", 18) {\\n using SafeTransferLib for address;\\n\\n event Deposit(address indexed from, uint256 amount);\\n\\n event Withdrawal(address indexed to, uint256 amount);\\n\\n function deposit() public payable virtual {\\n _mint(msg.sender, msg.value);\\n\\n emit Deposit(msg.sender, msg.value);\\n }\\n\\n function withdraw(uint256 amount) public virtual {\\n _burn(msg.sender, amount);\\n\\n emit Withdrawal(msg.sender, amount);\\n\\n msg.sender.safeTransferETH(amount);\\n }\\n\\n receive() external payable virtual {\\n deposit();\\n }\\n}\\n\"\r\n },\r\n \"lib/solmate/src/tokens/ERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\\nabstract contract ERC20 {\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /*//////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string public name;\\n\\n string public symbol;\\n\\n uint8 public immutable decimals;\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 public totalSupply;\\n\\n mapping(address => uint256) public balanceOf;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 internal immutable INITIAL_CHAIN_ID;\\n\\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\\n\\n mapping(address => uint256) public nonces;\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n constructor(\\n string memory _name,\\n string memory _symbol,\\n uint8 _decimals\\n ) {\\n name = _name;\\n symbol = _symbol;\\n decimals = _decimals;\\n\\n INITIAL_CHAIN_ID = block.chainid;\\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function approve(address spender, uint256 amount) public virtual returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n\\n return true;\\n }\\n\\n function transfer(address to, uint256 amount) public virtual returns (bool) {\\n balanceOf[msg.sender] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(msg.sender, to, amount);\\n\\n return true;\\n }\\n\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual returns (bool) {\\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\\n\\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\\n\\n balanceOf[from] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n return true;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 LOGIC\\n //////////////////////////////////////////////////////////////*/\\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 ) public virtual {\\n require(deadline >= block.timestamp, \\\"PERMIT_DEADLINE_EXPIRED\\\");\\n\\n // Unchecked because the only math done is incrementing\\n // the owner's nonce which cannot realistically overflow.\\n unchecked {\\n address recoveredAddress = ecrecover(\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR(),\\n keccak256(\\n abi.encode(\\n keccak256(\\n \\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\"\\n ),\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n require(recoveredAddress != address(0) && recoveredAddress == owner, \\\"INVALID_SIGNER\\\");\\n\\n allowance[recoveredAddress][spender] = value;\\n }\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\\n }\\n\\n function computeDomainSeparator() internal view virtual returns (bytes32) {\\n return\\n keccak256(\\n abi.encode(\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"),\\n keccak256(bytes(name)),\\n keccak256(\\\"1\\\"),\\n block.chainid,\\n address(this)\\n )\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _mint(address to, uint256 amount) internal virtual {\\n totalSupply += amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(address(0), to, amount);\\n }\\n\\n function _burn(address from, uint256 amount) internal virtual {\\n balanceOf[from] -= amount;\\n\\n // Cannot underflow because a user's balance\\n // will never be larger than the total supply.\\n unchecked {\\n totalSupply -= amount;\\n }\\n\\n emit Transfer(from, address(0), amount);\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IERC173.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\n/// @title ERC-173 Contract Ownership Standard\\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\\n/* is ERC165 */\\ninterface IERC173 {\\n /// @dev This emits when ownership of a contract changes.\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n /// @notice Get the address of the owner\\n /// @return owner_ The address of the owner.\\n function owner() external view returns (address owner_);\\n\\n /// @notice Set the address of the new owner of the contract\\n /// @dev Set _newOwner to address(0) to renounce any ownership.\\n /// @param _newOwner The address of the new owner of the contract\\n function transferOwnership(address _newOwner) external;\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_wrapper\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"Invalid\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NewOwnerMustNotBeSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoNullOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoPendingOwnershipTransfer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotPendingOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnAuthorized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes8\",\"name\":\"_transactionId\",\"type\":\"bytes8\"}],\"name\":\"LiFiHopTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"cancelOwnershipTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"confirmOwnershipTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"decode_startBridgeTokensViaHopL1ERC20Packed\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"contract IHopBridge\",\"name\":\"hopBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacetOptimized.HopData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"decode_startBridgeTokensViaHopL1NativePacked\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"contract IHopBridge\",\"name\":\"hopBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacetOptimized.HopData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"decode_startBridgeTokensViaHopL2ERC20Packed\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"contract IHopBridge\",\"name\":\"hopBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacetOptimized.HopData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"decode_startBridgeTokensViaHopL2NativePacked\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"contract IHopBridge\",\"name\":\"hopBridge\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"}],\"internalType\":\"struct HopFacetOptimized.HopData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes8\",\"name\":\"transactionId\",\"type\":\"bytes8\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"hopBridge\",\"type\":\"address\"}],\"name\":\"encode_startBridgeTokensViaHopL1ERC20Packed\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes8\",\"name\":\"transactionId\",\"type\":\"bytes8\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"hopBridge\",\"type\":\"address\"}],\"name\":\"encode_startBridgeTokensViaHopL1NativePacked\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"wrapper\",\"type\":\"address\"}],\"name\":\"encode_startBridgeTokensViaHopL2ERC20Packed\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes8\",\"name\":\"transactionId\",\"type\":\"bytes8\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"}],\"name\":\"encode_startBridgeTokensViaHopL2NativePacked\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nativeBridge\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nativeExchangeAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nativeHToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nativeL2CanonicalToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"bridges\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"tokensToApprove\",\"type\":\"address[]\"}],\"name\":\"setApprovalForHopBridges\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes8\",\"name\":\"transactionId\",\"type\":\"bytes8\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"hopBridge\",\"type\":\"address\"}],\"name\":\"startBridgeTokensViaHopL1ERC20Min\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBridgeTokensViaHopL1ERC20Packed\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes8\",\"name\":\"transactionId\",\"type\":\"bytes8\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"relayer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"hopBridge\",\"type\":\"address\"}],\"name\":\"startBridgeTokensViaHopL1NativeMin\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBridgeTokensViaHopL1NativePacked\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes8\",\"name\":\"transactionId\",\"type\":\"bytes8\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"hopBridge\",\"type\":\"address\"}],\"name\":\"startBridgeTokensViaHopL2ERC20Min\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBridgeTokensViaHopL2ERC20Packed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes8\",\"name\":\"transactionId\",\"type\":\"bytes8\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"bonderFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationAmountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationDeadline\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"hopBridge\",\"type\":\"address\"}],\"name\":\"startBridgeTokensViaHopL2NativeMin\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBridgeTokensViaHopL2NativePacked\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ContractName: "HopFacetPacked", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "00000000000000000000000011f11121df7256c40339393b0fb045321022ce440000000000000000000000000000000000000000000000000000000000000000", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/HopFacetPacked.sol": { + "content": "// // SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IHopBridge, IL2AmmWrapper, ISwap } from \"../Interfaces/IHopBridge.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { ERC20, SafeTransferLib } from \"solmate/utils/SafeTransferLib.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { TransferrableOwnership } from \"../Helpers/TransferrableOwnership.sol\";\nimport { HopFacetOptimized } from \"lifi/Facets/HopFacetOptimized.sol\";\nimport { WETH } from \"solmate/tokens/WETH.sol\";\n\n/// @title Hop Facet (Optimized for Rollups)\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Hop\n/// @custom:version 1.0.6\ncontract HopFacetPacked is ILiFi, TransferrableOwnership {\n using SafeTransferLib for ERC20;\n\n /// Storage ///\n\n address public immutable nativeBridge;\n address public immutable nativeL2CanonicalToken;\n address public immutable nativeHToken;\n address public immutable nativeExchangeAddress;\n\n /// Errors ///\n\n error Invalid();\n\n /// Events ///\n\n event LiFiHopTransfer(bytes8 _transactionId);\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _owner The contract owner to approve tokens.\n /// @param _wrapper The address of Hop L2_AmmWrapper for native asset.\n constructor(\n address _owner,\n address _wrapper\n ) TransferrableOwnership(_owner) {\n bool wrapperIsSet = _wrapper != address(0);\n\n if (block.chainid == 1 && wrapperIsSet) {\n revert Invalid();\n }\n\n nativeL2CanonicalToken = wrapperIsSet\n ? IL2AmmWrapper(_wrapper).l2CanonicalToken()\n : address(0);\n nativeHToken = wrapperIsSet\n ? IL2AmmWrapper(_wrapper).hToken()\n : address(0);\n nativeExchangeAddress = wrapperIsSet\n ? IL2AmmWrapper(_wrapper).exchangeAddress()\n : address(0);\n nativeBridge = wrapperIsSet\n ? IL2AmmWrapper(_wrapper).bridge()\n : address(0);\n }\n\n /// External Methods ///\n\n /// @dev Only meant to be called outside of the context of the diamond\n /// @notice Sets approval for the Hop Bridge to spend the specified token\n /// @param bridges The Hop Bridges to approve\n /// @param tokensToApprove The tokens to approve to approve to the Hop Bridges\n function setApprovalForHopBridges(\n address[] calldata bridges,\n address[] calldata tokensToApprove\n ) external onlyOwner {\n uint256 numBridges = bridges.length;\n\n for (uint256 i; i < numBridges; i++) {\n // Give Hop approval to bridge tokens\n LibAsset.maxApproveERC20(\n IERC20(tokensToApprove[i]),\n address(bridges[i]),\n type(uint256).max\n );\n }\n }\n\n /// @notice Bridges Native tokens via Hop Protocol from L2\n /// No params, all data will be extracted from manually encoded callData\n function startBridgeTokensViaHopL2NativePacked() external payable {\n // first 4 bytes are function signature\n // transactionId: bytes8(msg.data[4:12]),\n // receiver: address(bytes20(msg.data[12:32])),\n // destinationChainId: uint256(uint32(bytes4(msg.data[32:36]))),\n // bonderFee: uint256(uint128(bytes16(msg.data[36:52]))),\n // amountOutMin: uint256(uint128(bytes16(msg.data[52:68])))\n // => total calldata length required: 68\n\n uint256 destinationChainId = uint256(uint32(bytes4(msg.data[32:36])));\n uint256 amountOutMin = uint256(uint128(bytes16(msg.data[52:68])));\n bool toL1 = destinationChainId == 1;\n\n // Wrap ETH\n WETH(payable(nativeL2CanonicalToken)).deposit{ value: msg.value }();\n\n // Exchange WETH for hToken\n uint256 swapAmount = ISwap(nativeExchangeAddress).swap(\n 0,\n 1,\n msg.value,\n amountOutMin,\n block.timestamp\n );\n\n // Bridge assets\n // solhint-disable-next-line check-send-result\n IHopBridge(nativeBridge).send(\n destinationChainId,\n address(bytes20(msg.data[12:32])), // receiver\n swapAmount,\n uint256(uint128(bytes16(msg.data[36:52]))), // bonderFee\n toL1 ? 0 : amountOutMin,\n toL1 ? 0 : block.timestamp + 7 * 24 * 60 * 60\n );\n\n emit LiFiHopTransfer(\n bytes8(msg.data[4:12]) // transactionId\n );\n }\n\n /// @notice Bridges Native tokens via Hop Protocol from L2\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param bonderFee Fees payed to hop bonder\n /// @param amountOutMin Source swap minimal accepted amount\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\n /// @param destinationDeadline Destination swap maximal time\n /// @param hopBridge Address of the Hop L2_AmmWrapper\n function startBridgeTokensViaHopL2NativeMin(\n bytes8 transactionId,\n address receiver,\n uint256 destinationChainId,\n uint256 bonderFee,\n uint256 amountOutMin,\n uint256 destinationAmountOutMin,\n uint256 destinationDeadline,\n address hopBridge\n ) external payable {\n // Bridge assets\n IHopBridge(hopBridge).swapAndSend{ value: msg.value }(\n destinationChainId,\n receiver,\n msg.value,\n bonderFee,\n amountOutMin,\n block.timestamp,\n destinationAmountOutMin,\n destinationDeadline\n );\n\n emit LiFiHopTransfer(transactionId);\n }\n\n /// @notice Bridges Native tokens via Hop Protocol from L2\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param bonderFee Fees payed to hop bonder\n /// @param amountOutMin Source swap minimal accepted amount\n function encode_startBridgeTokensViaHopL2NativePacked(\n bytes8 transactionId,\n address receiver,\n uint256 destinationChainId,\n uint256 bonderFee,\n uint256 amountOutMin\n ) external pure returns (bytes memory) {\n require(\n destinationChainId <= type(uint32).max,\n \"destinationChainId value passed too big to fit in uint32\"\n );\n require(\n bonderFee <= type(uint128).max,\n \"bonderFee value passed too big to fit in uint128\"\n );\n require(\n amountOutMin <= type(uint128).max,\n \"amountOutMin value passed too big to fit in uint128\"\n );\n\n return\n bytes.concat(\n HopFacetPacked.startBridgeTokensViaHopL2NativePacked.selector,\n bytes8(transactionId),\n bytes20(receiver),\n bytes4(uint32(destinationChainId)),\n bytes16(uint128(bonderFee)),\n bytes16(uint128(amountOutMin))\n );\n }\n\n /// @notice Decodes calldata for startBridgeTokensViaHopL2NativePacked\n /// @param _data the calldata to decode\n function decode_startBridgeTokensViaHopL2NativePacked(\n bytes calldata _data\n )\n external\n pure\n returns (BridgeData memory, HopFacetOptimized.HopData memory)\n {\n require(\n _data.length >= 68,\n \"data passed in is not the correct length\"\n );\n\n BridgeData memory bridgeData;\n HopFacetOptimized.HopData memory hopData;\n\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\n bridgeData.receiver = address(bytes20(_data[12:32]));\n bridgeData.destinationChainId = uint256(uint32(bytes4(_data[32:36])));\n hopData.bonderFee = uint256(uint128(bytes16(_data[36:52])));\n hopData.amountOutMin = uint256(uint128(bytes16(_data[52:68])));\n\n return (bridgeData, hopData);\n }\n\n /// @notice Bridges ERC20 tokens via Hop Protocol from L2\n /// No params, all data will be extracted from manually encoded callData\n function startBridgeTokensViaHopL2ERC20Packed() external {\n // first 4 bytes are function signature\n // transactionId: bytes8(msg.data[4:12]),\n // receiver: address(bytes20(msg.data[12:32])),\n // destinationChainId: uint256(uint32(bytes4(msg.data[32:36]))),\n // sendingAssetId: address(bytes20(msg.data[36:56])),\n // amount: uint256(uint128(bytes16(msg.data[56:72]))),\n // bonderFee: uint256(uint128(bytes16(msg.data[72:88]))),\n // amountOutMin: uint256(uint128(bytes16(msg.data[88:104]))),\n // destinationAmountOutMin: uint256(uint128(bytes16(msg.data[104:120]))),\n // destinationDeadline: uint256(uint32(bytes4(msg.data[120:124]))),\n // wrapper: address(bytes20(msg.data[124:144]))\n // => total calldata length required: 144\n\n uint256 destinationChainId = uint256(uint32(bytes4(msg.data[32:36])));\n uint256 amount = uint256(uint128(bytes16(msg.data[56:72])));\n uint256 amountOutMin = uint256(uint128(bytes16(msg.data[88:104])));\n bool toL1 = destinationChainId == 1;\n\n IL2AmmWrapper wrapper = IL2AmmWrapper(\n address(bytes20(msg.data[124:144]))\n );\n\n // Deposit assets\n ERC20(address(bytes20(msg.data[36:56]))).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n\n // Exchange sending asset to hToken\n uint256 swapAmount = ISwap(wrapper.exchangeAddress()).swap(\n 0,\n 1,\n amount,\n amountOutMin,\n block.timestamp\n );\n\n // Bridge assets\n // solhint-disable-next-line check-send-result\n IHopBridge(wrapper.bridge()).send(\n destinationChainId,\n address(bytes20(msg.data[12:32])),\n swapAmount,\n uint256(uint128(bytes16(msg.data[72:88]))),\n toL1 ? 0 : uint256(uint128(bytes16(msg.data[104:120]))),\n toL1 ? 0 : uint256(uint32(bytes4(msg.data[120:124])))\n );\n\n emit LiFiHopTransfer(bytes8(msg.data[4:12]));\n }\n\n /// @notice Bridges ERC20 tokens via Hop Protocol from L2\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param sendingAssetId Address of the source asset to bridge\n /// @param minAmount Amount of the source asset to bridge\n /// @param bonderFee Fees payed to hop bonder\n /// @param amountOutMin Source swap minimal accepted amount\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\n /// @param destinationDeadline Destination swap maximal time\n /// @param hopBridge Address of the Hop L2_AmmWrapper\n function startBridgeTokensViaHopL2ERC20Min(\n bytes8 transactionId,\n address receiver,\n uint256 destinationChainId,\n address sendingAssetId,\n uint256 minAmount,\n uint256 bonderFee,\n uint256 amountOutMin,\n uint256 destinationAmountOutMin,\n uint256 destinationDeadline,\n address hopBridge\n ) external {\n // Deposit assets\n ERC20(sendingAssetId).safeTransferFrom(\n msg.sender,\n address(this),\n minAmount\n );\n\n // Bridge assets\n IHopBridge(hopBridge).swapAndSend(\n destinationChainId,\n receiver,\n minAmount,\n bonderFee,\n amountOutMin,\n block.timestamp,\n destinationAmountOutMin,\n destinationDeadline\n );\n\n emit LiFiHopTransfer(transactionId);\n }\n\n /// @notice Bridges ERC20 tokens via Hop Protocol from L2\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param sendingAssetId Address of the source asset to bridge\n /// @param minAmount Amount of the source asset to bridge\n /// @param bonderFee Fees payed to hop bonder\n /// @param amountOutMin Source swap minimal accepted amount\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\n /// @param destinationDeadline Destination swap maximal time\n /// @param wrapper Address of the Hop L2_AmmWrapper\n function encode_startBridgeTokensViaHopL2ERC20Packed(\n bytes32 transactionId,\n address receiver,\n uint256 destinationChainId,\n address sendingAssetId,\n uint256 minAmount,\n uint256 bonderFee,\n uint256 amountOutMin,\n uint256 destinationAmountOutMin,\n uint256 destinationDeadline,\n address wrapper\n ) external pure returns (bytes memory) {\n require(\n destinationChainId <= type(uint32).max,\n \"destinationChainId value passed too big to fit in uint32\"\n );\n require(\n minAmount <= type(uint128).max,\n \"amount value passed too big to fit in uint128\"\n );\n require(\n bonderFee <= type(uint128).max,\n \"bonderFee value passed too big to fit in uint128\"\n );\n require(\n amountOutMin <= type(uint128).max,\n \"amountOutMin value passed too big to fit in uint128\"\n );\n require(\n destinationAmountOutMin <= type(uint128).max,\n \"destinationAmountOutMin value passed too big to fit in uint128\"\n );\n require(\n destinationDeadline <= type(uint32).max,\n \"destinationDeadline value passed too big to fit in uint32\"\n );\n\n return\n bytes.concat(\n HopFacetPacked.startBridgeTokensViaHopL2ERC20Packed.selector,\n bytes8(transactionId),\n bytes20(receiver),\n bytes4(uint32(destinationChainId)),\n bytes20(sendingAssetId),\n bytes16(uint128(minAmount)),\n bytes16(uint128(bonderFee)),\n bytes16(uint128(amountOutMin)),\n bytes16(uint128(destinationAmountOutMin)),\n bytes4(uint32(destinationDeadline)),\n bytes20(wrapper)\n );\n }\n\n /// @notice Decodes calldata for startBridgeTokensViaHopL2ERC20Packed\n /// @param _data the calldata to decode\n function decode_startBridgeTokensViaHopL2ERC20Packed(\n bytes calldata _data\n )\n external\n pure\n returns (BridgeData memory, HopFacetOptimized.HopData memory)\n {\n require(\n _data.length >= 144,\n \"data passed in is not the correct length\"\n );\n\n BridgeData memory bridgeData;\n HopFacetOptimized.HopData memory hopData;\n\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\n bridgeData.receiver = address(bytes20(_data[12:32]));\n bridgeData.destinationChainId = uint256(uint32(bytes4(_data[32:36])));\n bridgeData.sendingAssetId = address(bytes20(_data[36:56]));\n bridgeData.minAmount = uint256(uint128(bytes16(_data[56:72])));\n hopData.bonderFee = uint256(uint128(bytes16(_data[72:88])));\n hopData.amountOutMin = uint256(uint128(bytes16(_data[88:104])));\n hopData.destinationAmountOutMin = uint256(\n uint128(bytes16(_data[104:120]))\n );\n hopData.destinationDeadline = uint256(uint32(bytes4(_data[120:124])));\n hopData.hopBridge = IHopBridge(address(bytes20(_data[124:144])));\n\n return (bridgeData, hopData);\n }\n\n /// @notice Bridges Native tokens via Hop Protocol from L1\n /// No params, all data will be extracted from manually encoded callData\n function startBridgeTokensViaHopL1NativePacked() external payable {\n // first 4 bytes are function signature\n // transactionId: bytes8(msg.data[4:12]),\n // receiver: address(bytes20(msg.data[12:32])),\n // destinationChainId: uint256(uint32(bytes4(msg.data[32:36]))),\n // destinationAmountOutMin: uint256(uint128(bytes16(msg.data[36:52]))),\n // relayer: address(bytes20(msg.data[52:72])),\n // relayerFee: uint256(uint128(bytes16(msg.data[72:88]))),\n // hopBridge: address(bytes20(msg.data[88:108]))\n // => total calldata length required: 108\n\n // Bridge assets\n IHopBridge(address(bytes20(msg.data[88:108]))).sendToL2{\n value: msg.value\n }(\n uint256(uint32(bytes4(msg.data[32:36]))),\n address(bytes20(msg.data[12:32])),\n msg.value,\n uint256(uint128(bytes16(msg.data[36:52]))),\n block.timestamp + 7 * 24 * 60 * 60,\n address(bytes20(msg.data[52:72])),\n uint256(uint128(bytes16(msg.data[72:88])))\n );\n\n emit LiFiHopTransfer(bytes8(msg.data[4:12]));\n }\n\n /// @notice Bridges Native tokens via Hop Protocol from L1\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\n /// @param relayer needed for gas spikes\n /// @param relayerFee needed for gas spikes\n /// @param hopBridge Address of the Hop Bridge\n function startBridgeTokensViaHopL1NativeMin(\n bytes8 transactionId,\n address receiver,\n uint256 destinationChainId,\n uint256 destinationAmountOutMin,\n address relayer,\n uint256 relayerFee,\n address hopBridge\n ) external payable {\n // Bridge assets\n IHopBridge(hopBridge).sendToL2{ value: msg.value }(\n destinationChainId,\n receiver,\n msg.value,\n destinationAmountOutMin,\n block.timestamp + 7 * 24 * 60 * 60,\n relayer,\n relayerFee\n );\n\n emit LiFiHopTransfer(transactionId);\n }\n\n /// @notice Bridges Native tokens via Hop Protocol from L1\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\n /// @param relayer needed for gas spikes\n /// @param relayerFee needed for gas spikes\n /// @param hopBridge Address of the Hop Bridge\n function encode_startBridgeTokensViaHopL1NativePacked(\n bytes8 transactionId,\n address receiver,\n uint256 destinationChainId,\n uint256 destinationAmountOutMin,\n address relayer,\n uint256 relayerFee,\n address hopBridge\n ) external pure returns (bytes memory) {\n require(\n destinationChainId <= type(uint32).max,\n \"destinationChainId value passed too big to fit in uint32\"\n );\n require(\n destinationAmountOutMin <= type(uint128).max,\n \"destinationAmountOutMin value passed too big to fit in uint128\"\n );\n require(\n relayerFee <= type(uint128).max,\n \"relayerFee value passed too big to fit in uint128\"\n );\n\n return\n bytes.concat(\n HopFacetPacked.startBridgeTokensViaHopL1NativePacked.selector,\n bytes8(transactionId),\n bytes20(receiver),\n bytes4(uint32(destinationChainId)),\n bytes16(uint128(destinationAmountOutMin)),\n bytes20(relayer),\n bytes16(uint128(relayerFee)),\n bytes20(hopBridge)\n );\n }\n\n /// @notice Decodes calldata for startBridgeTokensViaHopL1NativePacked\n /// @param _data the calldata to decode\n function decode_startBridgeTokensViaHopL1NativePacked(\n bytes calldata _data\n )\n external\n pure\n returns (BridgeData memory, HopFacetOptimized.HopData memory)\n {\n require(\n _data.length >= 108,\n \"data passed in is not the correct length\"\n );\n\n BridgeData memory bridgeData;\n HopFacetOptimized.HopData memory hopData;\n\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\n bridgeData.receiver = address(bytes20(_data[12:32]));\n bridgeData.destinationChainId = uint256(uint32(bytes4(_data[32:36])));\n hopData.destinationAmountOutMin = uint256(\n uint128(bytes16(_data[36:52]))\n );\n // relayer = address(bytes20(_data[52:72]));\n // relayerFee = uint256(uint128(bytes16(_data[72:88])));\n hopData.hopBridge = IHopBridge(address(bytes20(_data[88:108])));\n\n return (bridgeData, hopData);\n }\n\n /// @notice Bridges Native tokens via Hop Protocol from L1\n /// No params, all data will be extracted from manually encoded callData\n function startBridgeTokensViaHopL1ERC20Packed() external payable {\n // first 4 bytes are function signature\n // transactionId: bytes8(msg.data[4:12]),\n // receiver: address(bytes20(msg.data[12:32])),\n // destinationChainId: uint256(uint32(bytes4(msg.data[32:36]))),\n // sendingAssetId: address(bytes20(msg.data[36:56])),\n // amount: uint256(uint128(bytes16(msg.data[56:72]))),\n // destinationAmountOutMin: uint256(uint128(bytes16(msg.data[72:88]))),\n // relayer: address(bytes20(msg.data[88:108])),\n // relayerFee: uint256(uint128(bytes16(msg.data[108:124]))),\n // hopBridge: address(bytes20(msg.data[124:144]))\n // => total calldata length required: 144\n\n uint256 amount = uint256(uint128(bytes16(msg.data[56:72])));\n\n // Deposit assets\n ERC20(address(bytes20(msg.data[36:56]))).safeTransferFrom(\n msg.sender,\n address(this),\n amount\n );\n\n // Bridge assets\n IHopBridge(address(bytes20(msg.data[124:144]))).sendToL2(\n uint256(uint32(bytes4(msg.data[32:36]))),\n address(bytes20(msg.data[12:32])),\n amount,\n uint256(uint128(bytes16(msg.data[72:88]))),\n block.timestamp + 7 * 24 * 60 * 60,\n address(bytes20(msg.data[88:108])),\n uint256(uint128(bytes16(msg.data[108:124])))\n );\n\n emit LiFiHopTransfer(bytes8(msg.data[4:12]));\n }\n\n /// @notice Bridges ERC20 tokens via Hop Protocol from L1\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param sendingAssetId Address of the source asset to bridge\n /// @param minAmount Amount of the source asset to bridge\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\n /// @param relayer needed for gas spikes\n /// @param relayerFee needed for gas spikes\n /// @param hopBridge Address of the Hop Bridge\n function startBridgeTokensViaHopL1ERC20Min(\n bytes8 transactionId,\n address receiver,\n uint256 destinationChainId,\n address sendingAssetId,\n uint256 minAmount,\n uint256 destinationAmountOutMin,\n address relayer,\n uint256 relayerFee,\n address hopBridge\n ) external {\n // Deposit assets\n ERC20(sendingAssetId).safeTransferFrom(\n msg.sender,\n address(this),\n minAmount\n );\n\n // Bridge assets\n IHopBridge(hopBridge).sendToL2(\n destinationChainId,\n receiver,\n minAmount,\n destinationAmountOutMin,\n block.timestamp + 7 * 24 * 60 * 60,\n relayer,\n relayerFee\n );\n\n emit LiFiHopTransfer(transactionId);\n }\n\n /// @notice Bridges ERC20 tokens via Hop Protocol from L1\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param destinationChainId Receiving chain\n /// @param sendingAssetId Address of the source asset to bridge\n /// @param minAmount Amount of the source asset to bridge\n /// @param destinationAmountOutMin Destination swap minimal accepted amount\n /// @param relayer needed for gas spikes\n /// @param relayerFee needed for gas spikes\n /// @param hopBridge Address of the Hop Bridge\n function encode_startBridgeTokensViaHopL1ERC20Packed(\n bytes8 transactionId,\n address receiver,\n uint256 destinationChainId,\n address sendingAssetId,\n uint256 minAmount,\n uint256 destinationAmountOutMin,\n address relayer,\n uint256 relayerFee,\n address hopBridge\n ) external pure returns (bytes memory) {\n require(\n destinationChainId <= type(uint32).max,\n \"destinationChainId value passed too big to fit in uint32\"\n );\n require(\n minAmount <= type(uint128).max,\n \"amount value passed too big to fit in uint128\"\n );\n require(\n destinationAmountOutMin <= type(uint128).max,\n \"destinationAmountOutMin value passed too big to fit in uint128\"\n );\n require(\n relayerFee <= type(uint128).max,\n \"relayerFee value passed too big to fit in uint128\"\n );\n\n return\n bytes.concat(\n HopFacetPacked.startBridgeTokensViaHopL1ERC20Packed.selector,\n bytes8(transactionId),\n bytes20(receiver),\n bytes4(uint32(destinationChainId)),\n bytes20(sendingAssetId),\n bytes16(uint128(minAmount)),\n bytes16(uint128(destinationAmountOutMin)),\n bytes20(relayer),\n bytes16(uint128(relayerFee)),\n bytes20(hopBridge)\n );\n }\n\n /// @notice Decodes calldata for startBridgeTokensViaHopL1ERC20Packed\n /// @param _data the calldata to decode\n function decode_startBridgeTokensViaHopL1ERC20Packed(\n bytes calldata _data\n )\n external\n pure\n returns (BridgeData memory, HopFacetOptimized.HopData memory)\n {\n require(\n _data.length >= 144,\n \"data passed in is not the correct length\"\n );\n\n BridgeData memory bridgeData;\n HopFacetOptimized.HopData memory hopData;\n\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\n bridgeData.receiver = address(bytes20(_data[12:32]));\n bridgeData.destinationChainId = uint256(uint32(bytes4(_data[32:36])));\n bridgeData.sendingAssetId = address(bytes20(_data[36:56]));\n bridgeData.minAmount = uint256(uint128(bytes16(_data[56:72])));\n hopData.destinationAmountOutMin = uint256(\n uint128(bytes16(_data[72:88]))\n );\n // relayer = address(bytes20(_data[88:108]));\n // relayerFee = uint256(uint128(bytes16(_data[108:124])));\n hopData.hopBridge = IHopBridge(address(bytes20(_data[124:144])));\n\n return (bridgeData, hopData);\n }\n}\n" + }, + "src/Interfaces/IHopBridge.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IHopBridge {\n function sendToL2(\n uint256 chainId,\n address recipient,\n uint256 amount,\n uint256 amountOutMin,\n uint256 deadline,\n address relayer,\n uint256 relayerFee\n ) external payable;\n\n function swapAndSend(\n uint256 chainId,\n address recipient,\n uint256 amount,\n uint256 bonderFee,\n uint256 amountOutMin,\n uint256 deadline,\n uint256 destinationAmountOutMin,\n uint256 destinationDeadline\n ) external payable;\n\n function send(\n uint256 chainId,\n address recipient,\n uint256 amount,\n uint256 bonderFee,\n uint256 amountOutMin,\n uint256 deadline\n ) external;\n}\n\ninterface IL2AmmWrapper {\n function bridge() external view returns (address);\n\n function l2CanonicalToken() external view returns (address);\n\n function hToken() external view returns (address);\n\n function exchangeAddress() external view returns (address);\n}\n\ninterface ISwap {\n function swap(\n uint8 tokenIndexFrom,\n uint8 tokenIndexTo,\n uint256 dx,\n uint256 minDy,\n uint256 deadline\n ) external returns (uint256);\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "lib/solmate/src/utils/SafeTransferLib.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20} from \"../tokens/ERC20.sol\";\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n /*//////////////////////////////////////////////////////////////\n ETH OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferETH(address to, uint256 amount) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Transfer the ETH and store if it succeeded or not.\n success := call(gas(), to, amount, 0, 0, 0, 0)\n }\n\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferFrom(\n ERC20 token,\n address from,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), from) // Append the \"from\" argument.\n mstore(add(freeMemoryPointer, 36), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 68), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FROM_FAILED\");\n }\n\n function safeTransfer(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FAILED\");\n }\n\n function safeApprove(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"APPROVE_FAILED\");\n }\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/TransferrableOwnership.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IERC173 } from \"../Interfaces/IERC173.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\n\ncontract TransferrableOwnership is IERC173 {\n address public owner;\n address public pendingOwner;\n\n /// Errors ///\n error UnAuthorized();\n error NoNullOwner();\n error NewOwnerMustNotBeSelf();\n error NoPendingOwnershipTransfer();\n error NotPendingOwner();\n\n /// Events ///\n event OwnershipTransferRequested(\n address indexed _from,\n address indexed _to\n );\n\n constructor(address initialOwner) {\n owner = initialOwner;\n }\n\n modifier onlyOwner() {\n if (msg.sender != owner) revert UnAuthorized();\n _;\n }\n\n /// @notice Initiates transfer of ownership to a new address\n /// @param _newOwner the address to transfer ownership to\n function transferOwnership(address _newOwner) external onlyOwner {\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\n pendingOwner = _newOwner;\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\n }\n\n /// @notice Cancel transfer of ownership\n function cancelOwnershipTransfer() external onlyOwner {\n if (pendingOwner == LibAsset.NULL_ADDRESS)\n revert NoPendingOwnershipTransfer();\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\n function confirmOwnershipTransfer() external {\n address _pendingOwner = pendingOwner;\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n}\n" + }, + "src/Facets/HopFacetOptimized.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IHopBridge } from \"../Interfaces/IHopBridge.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\n\n/// @title Hop Facet (Optimized)\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Hop\n/// @custom:version 2.0.0\ncontract HopFacetOptimized is ILiFi, SwapperV2 {\n /// Types ///\n\n struct HopData {\n uint256 bonderFee;\n uint256 amountOutMin;\n uint256 deadline;\n uint256 destinationAmountOutMin;\n uint256 destinationDeadline;\n IHopBridge hopBridge;\n address relayer;\n uint256 relayerFee;\n uint256 nativeFee;\n }\n\n /// External Methods ///\n\n /// @notice Sets approval for the Hop Bridge to spend the specified token\n /// @param bridges The Hop Bridges to approve\n /// @param tokensToApprove The tokens to approve to approve to the Hop Bridges\n function setApprovalForBridges(\n address[] calldata bridges,\n address[] calldata tokensToApprove\n ) external {\n LibDiamond.enforceIsContractOwner();\n for (uint256 i; i < bridges.length; i++) {\n // Give Hop approval to bridge tokens\n LibAsset.maxApproveERC20(\n IERC20(tokensToApprove[i]),\n address(bridges[i]),\n type(uint256).max\n );\n }\n }\n\n /// @notice Bridges ERC20 tokens via Hop Protocol from L1\n /// @param _bridgeData the core information needed for bridging\n /// @param _hopData data specific to Hop Protocol\n function startBridgeTokensViaHopL1ERC20(\n ILiFi.BridgeData calldata _bridgeData,\n HopData calldata _hopData\n ) external payable {\n // Deposit assets\n LibAsset.transferFromERC20(\n _bridgeData.sendingAssetId,\n msg.sender,\n address(this),\n _bridgeData.minAmount\n );\n // Bridge assets\n _hopData.hopBridge.sendToL2{ value: _hopData.nativeFee }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline,\n _hopData.relayer,\n _hopData.relayerFee\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Bridges Native tokens via Hop Protocol from L1\n /// @param _bridgeData the core information needed for bridging\n /// @param _hopData data specific to Hop Protocol\n function startBridgeTokensViaHopL1Native(\n ILiFi.BridgeData calldata _bridgeData,\n HopData calldata _hopData\n ) external payable {\n // Bridge assets\n _hopData.hopBridge.sendToL2{\n value: _bridgeData.minAmount + _hopData.nativeFee\n }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline,\n _hopData.relayer,\n _hopData.relayerFee\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging ERC20 tokens via Hop Protocol from L1\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _hopData data specific to Hop Protocol\n function swapAndStartBridgeTokensViaHopL1ERC20(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n HopData calldata _hopData\n ) external payable {\n // Deposit and swap assets\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n _hopData.nativeFee\n );\n\n // Bridge assets\n _hopData.hopBridge.sendToL2{ value: _hopData.nativeFee }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline,\n _hopData.relayer,\n _hopData.relayerFee\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging Native tokens via Hop Protocol from L1\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _hopData data specific to Hop Protocol\n function swapAndStartBridgeTokensViaHopL1Native(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n HopData calldata _hopData\n ) external payable {\n // Deposit and swap assets\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n _hopData.nativeFee\n );\n\n // Bridge assets\n _hopData.hopBridge.sendToL2{\n value: _bridgeData.minAmount + _hopData.nativeFee\n }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline,\n _hopData.relayer,\n _hopData.relayerFee\n );\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Bridges ERC20 tokens via Hop Protocol from L2\n /// @param _bridgeData the core information needed for bridging\n /// @param _hopData data specific to Hop Protocol\n function startBridgeTokensViaHopL2ERC20(\n ILiFi.BridgeData calldata _bridgeData,\n HopData calldata _hopData\n ) external {\n // Deposit assets\n LibAsset.transferFromERC20(\n _bridgeData.sendingAssetId,\n msg.sender,\n address(this),\n _bridgeData.minAmount\n );\n // Bridge assets\n _hopData.hopBridge.swapAndSend(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.bonderFee,\n _hopData.amountOutMin,\n _hopData.deadline,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Bridges Native tokens via Hop Protocol from L2\n /// @param _bridgeData the core information needed for bridging\n /// @param _hopData data specific to Hop Protocol\n function startBridgeTokensViaHopL2Native(\n ILiFi.BridgeData calldata _bridgeData,\n HopData calldata _hopData\n ) external payable {\n // Bridge assets\n _hopData.hopBridge.swapAndSend{ value: _bridgeData.minAmount }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.bonderFee,\n _hopData.amountOutMin,\n _hopData.deadline,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging ERC20 tokens via Hop Protocol from L2\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _hopData data specific to Hop Protocol\n function swapAndStartBridgeTokensViaHopL2ERC20(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n HopData calldata _hopData\n ) external payable {\n // Deposit and swap assets\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n // Bridge assets\n _hopData.hopBridge.swapAndSend(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.bonderFee,\n _hopData.amountOutMin,\n _hopData.deadline,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging Native tokens via Hop Protocol from L2\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _hopData data specific to Hop Protocol\n function swapAndStartBridgeTokensViaHopL2Native(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n HopData calldata _hopData\n ) external payable {\n // Deposit and swap assets\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n // Bridge assets\n _hopData.hopBridge.swapAndSend{ value: _bridgeData.minAmount }(\n _bridgeData.destinationChainId,\n _bridgeData.receiver,\n _bridgeData.minAmount,\n _hopData.bonderFee,\n _hopData.amountOutMin,\n _hopData.deadline,\n _hopData.destinationAmountOutMin,\n _hopData.destinationDeadline\n );\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "lib/solmate/src/tokens/WETH.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20} from \"./ERC20.sol\";\n\nimport {SafeTransferLib} from \"../utils/SafeTransferLib.sol\";\n\n/// @notice Minimalist and modern Wrapped Ether implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/WETH.sol)\n/// @author Inspired by WETH9 (https://github.com/dapphub/ds-weth/blob/master/src/weth9.sol)\ncontract WETH is ERC20(\"Wrapped Ether\", \"WETH\", 18) {\n using SafeTransferLib for address;\n\n event Deposit(address indexed from, uint256 amount);\n\n event Withdrawal(address indexed to, uint256 amount);\n\n function deposit() public payable virtual {\n _mint(msg.sender, msg.value);\n\n emit Deposit(msg.sender, msg.value);\n }\n\n function withdraw(uint256 amount) public virtual {\n _burn(msg.sender, amount);\n\n emit Withdrawal(msg.sender, amount);\n\n msg.sender.safeTransferETH(amount);\n }\n\n receive() external payable virtual {\n deposit();\n }\n}\n" + }, + "lib/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\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 ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Interfaces/IERC173.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\n/// @title ERC-173 Contract Ownership Standard\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\n/* is ERC165 */\ninterface IERC173 {\n /// @dev This emits when ownership of a contract changes.\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n /// @notice Get the address of the owner\n /// @return owner_ The address of the owner.\n function owner() external view returns (address owner_);\n\n /// @notice Set the address of the new owner of the contract\n /// @dev Set _newOwner to address(0) to renounce any ownership.\n /// @param _newOwner The address of the new owner of the contract\n function transferOwnership(address _newOwner) external;\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.6 + Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... |CelerCircleBridgeFacet +0x6731c946747ba54c78e7a65d416cde39e478eceb +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/CelerCircleBridgeFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { ICircleBridgeProxy } from \\\"../Interfaces/ICircleBridgeProxy.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title CelerCircleBridge Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through CelerCircleBridge\\n/// @custom:version 1.0.1\\ncontract CelerCircleBridgeFacet is\\n ILiFi,\\n ReentrancyGuard,\\n SwapperV2,\\n Validatable\\n{\\n /// Storage ///\\n\\n /// @notice The address of the CircleBridgeProxy on the current chain.\\n ICircleBridgeProxy private immutable circleBridgeProxy;\\n\\n /// @notice The USDC address on the current chain.\\n address private immutable usdc;\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _circleBridgeProxy The address of the CircleBridgeProxy on the current chain.\\n /// @param _usdc The address of USDC on the current chain.\\n constructor(ICircleBridgeProxy _circleBridgeProxy, address _usdc) {\\n circleBridgeProxy = _circleBridgeProxy;\\n usdc = _usdc;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via CelerCircleBridge\\n /// @param _bridgeData Data containing core information for bridging\\n function startBridgeTokensViaCelerCircleBridge(\\n BridgeData calldata _bridgeData\\n )\\n external\\n nonReentrant\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n onlyAllowSourceToken(_bridgeData, usdc)\\n {\\n LibAsset.depositAsset(usdc, _bridgeData.minAmount);\\n _startBridge(_bridgeData);\\n }\\n\\n /// @notice Performs a swap before bridging via CelerCircleBridge\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n function swapAndStartBridgeTokensViaCelerCircleBridge(\\n BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n onlyAllowSourceToken(_bridgeData, usdc)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n _startBridge(_bridgeData);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via CelerCircleBridge\\n /// @param _bridgeData The core information needed for bridging\\n function _startBridge(BridgeData memory _bridgeData) private {\\n require(\\n _bridgeData.destinationChainId <= type(uint64).max,\\n \\\"_bridgeData.destinationChainId passed is too big to fit in uint64\\\"\\n );\\n\\n // give max approval for token to CelerCircleBridge bridge, if not already\\n LibAsset.maxApproveERC20(\\n IERC20(usdc),\\n address(circleBridgeProxy),\\n _bridgeData.minAmount\\n );\\n\\n // initiate bridge transaction\\n circleBridgeProxy.depositForBurn(\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n bytes32(uint256(uint160(_bridgeData.receiver))),\\n usdc\\n );\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/ICircleBridgeProxy.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ICircleBridgeProxy {\\n /// @notice Deposits and burns tokens from sender to be minted on destination domain.\\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\\n /// or approved allowance 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 _dstChid 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 function depositForBurn(\\n uint256 _amount,\\n uint64 _dstChid,\\n bytes32 _mintRecipient,\\n address _burnToken\\n ) external returns (uint64 nonce);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract ICircleBridgeProxy\",\"name\":\"_circleBridgeProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_usdc\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSendingToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaCelerCircleBridge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"}],\"name\":\"swapAndStartBridgeTokensViaCelerCircleBridge\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "CelerCircleBridgeFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000006065a982f04f759b7d2d042d2864e569fad84214000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/CelerCircleBridgeFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { ICircleBridgeProxy } from \"../Interfaces/ICircleBridgeProxy.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title CelerCircleBridge Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through CelerCircleBridge\n/// @custom:version 1.0.1\ncontract CelerCircleBridgeFacet is\n ILiFi,\n ReentrancyGuard,\n SwapperV2,\n Validatable\n{\n /// Storage ///\n\n /// @notice The address of the CircleBridgeProxy on the current chain.\n ICircleBridgeProxy private immutable circleBridgeProxy;\n\n /// @notice The USDC address on the current chain.\n address private immutable usdc;\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _circleBridgeProxy The address of the CircleBridgeProxy on the current chain.\n /// @param _usdc The address of USDC on the current chain.\n constructor(ICircleBridgeProxy _circleBridgeProxy, address _usdc) {\n circleBridgeProxy = _circleBridgeProxy;\n usdc = _usdc;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via CelerCircleBridge\n /// @param _bridgeData Data containing core information for bridging\n function startBridgeTokensViaCelerCircleBridge(\n BridgeData calldata _bridgeData\n )\n external\n nonReentrant\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n onlyAllowSourceToken(_bridgeData, usdc)\n {\n LibAsset.depositAsset(usdc, _bridgeData.minAmount);\n _startBridge(_bridgeData);\n }\n\n /// @notice Performs a swap before bridging via CelerCircleBridge\n /// @param _bridgeData The core information needed for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n function swapAndStartBridgeTokensViaCelerCircleBridge(\n BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n onlyAllowSourceToken(_bridgeData, usdc)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n _startBridge(_bridgeData);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via CelerCircleBridge\n /// @param _bridgeData The core information needed for bridging\n function _startBridge(BridgeData memory _bridgeData) private {\n require(\n _bridgeData.destinationChainId <= type(uint64).max,\n \"_bridgeData.destinationChainId passed is too big to fit in uint64\"\n );\n\n // give max approval for token to CelerCircleBridge bridge, if not already\n LibAsset.maxApproveERC20(\n IERC20(usdc),\n address(circleBridgeProxy),\n _bridgeData.minAmount\n );\n\n // initiate bridge transaction\n circleBridgeProxy.depositForBurn(\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n bytes32(uint256(uint160(_bridgeData.receiver))),\n usdc\n );\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/ICircleBridgeProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ICircleBridgeProxy {\n /// @notice Deposits and burns tokens from sender to be minted on destination domain.\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\n /// or approved allowance 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 _dstChid 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 function depositForBurn(\n uint256 _amount,\n uint64 _dstChid,\n bytes32 _mintRecipient,\n address _burnToken\n ) external returns (uint64 nonce);\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.1 + Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \CelerIMFacetMutable +0xf70a1ed85ecc454a562a4b69ee40cbc6a4eb0b64 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/CelerIMFacetMutable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { CelerIMFacetBase, IMessageBus, MsgDataTypes, IERC20, CelerIM } from \\\"../Helpers/CelerIMFacetBase.sol\\\";\\n\\n/// @title CelerIMFacetMutable\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging tokens and data through CBridge\\n/// @notice This contract is exclusively used for mutable diamond contracts\\n/// @custom:version 2.0.0\\ncontract CelerIMFacetMutable is CelerIMFacetBase {\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _messageBus The contract address of the cBridge Message Bus\\n /// @param _relayerOwner The address that will become the owner of the RelayerCelerIM contract\\n /// @param _diamondAddress The address of the diamond contract that will be connected with the RelayerCelerIM\\n /// @param _cfUSDC The contract address of the Celer Flow USDC\\n constructor(\\n IMessageBus _messageBus,\\n address _relayerOwner,\\n address _diamondAddress,\\n address _cfUSDC\\n ) CelerIMFacetBase(_messageBus, _relayerOwner, _diamondAddress, _cfUSDC) {}\\n}\\n\"\r\n },\r\n \"src/Helpers/CelerIMFacetBase.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ERC20 } from \\\"solmate/tokens/ERC20.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { InvalidAmount, InformationMismatch } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { MessageSenderLib, MsgDataTypes, IMessageBus } from \\\"celer-network/contracts/message/libraries/MessageSenderLib.sol\\\";\\nimport { RelayerCelerIM } from \\\"lifi/Periphery/RelayerCelerIM.sol\\\";\\n\\ninterface CelerToken {\\n function canonical() external returns (address);\\n}\\n\\ninterface CelerIM {\\n /// @param maxSlippage The max slippage accepted, given as percentage in point (pip).\\n /// @param nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\\n /// @param callTo The address of the contract to be called at destination.\\n /// @param callData The encoded calldata with below data\\n /// bytes32 transactionId,\\n /// LibSwap.SwapData[] memory swapData,\\n /// address receiver,\\n /// address refundAddress\\n /// @param messageBusFee The fee to be paid to CBridge message bus for relaying the message\\n /// @param bridgeType Defines the bridge operation type (must be one of the values of CBridge library MsgDataTypes.BridgeSendType)\\n struct CelerIMData {\\n uint32 maxSlippage;\\n uint64 nonce;\\n bytes callTo;\\n bytes callData;\\n uint256 messageBusFee;\\n MsgDataTypes.BridgeSendType bridgeType;\\n }\\n}\\n\\n/// @title CelerIM Facet Base\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging tokens and data through CBridge\\n/// @notice Used to differentiate between contract instances for mutable and immutable diamond as these cannot be shared\\n/// @custom:version 2.0.0\\nabstract contract CelerIMFacetBase is\\n ILiFi,\\n ReentrancyGuard,\\n SwapperV2,\\n Validatable\\n{\\n /// Storage ///\\n\\n /// @dev The contract address of the cBridge Message Bus\\n IMessageBus private immutable cBridgeMessageBus;\\n\\n /// @dev The contract address of the RelayerCelerIM\\n RelayerCelerIM public immutable relayer;\\n\\n /// @dev The contract address of the Celer Flow USDC\\n address private immutable cfUSDC;\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _messageBus The contract address of the cBridge Message Bus\\n /// @param _relayerOwner The address that will become the owner of the RelayerCelerIM contract\\n /// @param _diamondAddress The address of the diamond contract that will be connected with the RelayerCelerIM\\n /// @param _cfUSDC The contract address of the Celer Flow USDC\\n constructor(\\n IMessageBus _messageBus,\\n address _relayerOwner,\\n address _diamondAddress,\\n address _cfUSDC\\n ) {\\n // deploy RelayerCelerIM\\n relayer = new RelayerCelerIM(\\n address(_messageBus),\\n _relayerOwner,\\n _diamondAddress\\n );\\n\\n // store arguments in variables\\n cBridgeMessageBus = _messageBus;\\n cfUSDC = _cfUSDC;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via CBridge\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _celerIMData Data specific to CelerIM\\n function startBridgeTokensViaCelerIM(\\n ILiFi.BridgeData memory _bridgeData,\\n CelerIM.CelerIMData calldata _celerIMData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n validateDestinationCallFlag(_bridgeData, _celerIMData);\\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // Transfer ERC20 tokens directly to relayer\\n IERC20 asset = _getRightAsset(_bridgeData.sendingAssetId);\\n\\n // Deposit ERC20 token\\n uint256 prevBalance = asset.balanceOf(address(relayer));\\n SafeERC20.safeTransferFrom(\\n asset,\\n msg.sender,\\n address(relayer),\\n _bridgeData.minAmount\\n );\\n\\n if (\\n asset.balanceOf(address(relayer)) - prevBalance !=\\n _bridgeData.minAmount\\n ) {\\n revert InvalidAmount();\\n }\\n }\\n\\n _startBridge(_bridgeData, _celerIMData);\\n }\\n\\n /// @notice Performs a swap before bridging via CBridge\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _celerIMData Data specific to CelerIM\\n function swapAndStartBridgeTokensViaCelerIM(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n CelerIM.CelerIMData calldata _celerIMData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n validateDestinationCallFlag(_bridgeData, _celerIMData);\\n\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n _celerIMData.messageBusFee\\n );\\n\\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // Transfer ERC20 tokens directly to relayer\\n IERC20 asset = _getRightAsset(_bridgeData.sendingAssetId);\\n\\n // Deposit ERC20 token\\n uint256 prevBalance = asset.balanceOf(address(relayer));\\n SafeERC20.safeTransfer(\\n asset,\\n address(relayer),\\n _bridgeData.minAmount\\n );\\n\\n if (\\n asset.balanceOf(address(relayer)) - prevBalance !=\\n _bridgeData.minAmount\\n ) {\\n revert InvalidAmount();\\n }\\n }\\n\\n _startBridge(_bridgeData, _celerIMData);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via CBridge\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _celerIMData Data specific to CBridge\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n CelerIM.CelerIMData calldata _celerIMData\\n ) private {\\n // Assuming messageBusFee is pre-calculated off-chain and available in _celerIMData\\n // Determine correct native asset amount to be forwarded (if so) and send funds to relayer\\n uint256 msgValue = LibAsset.isNativeAsset(_bridgeData.sendingAssetId)\\n ? _bridgeData.minAmount\\n : 0;\\n\\n // Check if transaction contains a destination call\\n if (!_bridgeData.hasDestinationCall) {\\n // Case 'no': Simple bridge transfer - Send to receiver\\n relayer.sendTokenTransfer{ value: msgValue }(\\n _bridgeData,\\n _celerIMData\\n );\\n } else {\\n // Case 'yes': Bridge + Destination call - Send to relayer\\n\\n // save address of original recipient\\n address receiver = _bridgeData.receiver;\\n\\n // Set relayer as a receiver\\n _bridgeData.receiver = address(relayer);\\n\\n // send token transfer\\n (bytes32 transferId, address bridgeAddress) = relayer\\n .sendTokenTransfer{ value: msgValue }(\\n _bridgeData,\\n _celerIMData\\n );\\n\\n // Call message bus via relayer incl messageBusFee\\n relayer.forwardSendMessageWithTransfer{\\n value: _celerIMData.messageBusFee\\n }(\\n _bridgeData.receiver,\\n uint64(_bridgeData.destinationChainId),\\n bridgeAddress,\\n transferId,\\n _celerIMData.callData\\n );\\n\\n // Reset receiver of bridge data for event emission\\n _bridgeData.receiver = receiver;\\n }\\n\\n // emit LiFi event\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @dev Get right asset to transfer to relayer.\\n /// @param _sendingAssetId The address of asset to bridge.\\n /// @return _asset The address of asset to transfer to relayer.\\n function _getRightAsset(\\n address _sendingAssetId\\n ) private returns (IERC20 _asset) {\\n if (_sendingAssetId == cfUSDC) {\\n // special case for cfUSDC token\\n _asset = IERC20(CelerToken(_sendingAssetId).canonical());\\n } else {\\n // any other ERC20 token\\n _asset = IERC20(_sendingAssetId);\\n }\\n }\\n\\n function validateDestinationCallFlag(\\n ILiFi.BridgeData memory _bridgeData,\\n CelerIM.CelerIMData calldata _celerIMData\\n ) private pure {\\n if (\\n (_celerIMData.callData.length > 0) !=\\n _bridgeData.hasDestinationCall\\n ) {\\n revert InformationMismatch();\\n }\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"lib/solmate/src/tokens/ERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\\nabstract contract ERC20 {\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /*//////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string public name;\\n\\n string public symbol;\\n\\n uint8 public immutable decimals;\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 public totalSupply;\\n\\n mapping(address => uint256) public balanceOf;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 internal immutable INITIAL_CHAIN_ID;\\n\\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\\n\\n mapping(address => uint256) public nonces;\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n constructor(\\n string memory _name,\\n string memory _symbol,\\n uint8 _decimals\\n ) {\\n name = _name;\\n symbol = _symbol;\\n decimals = _decimals;\\n\\n INITIAL_CHAIN_ID = block.chainid;\\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function approve(address spender, uint256 amount) public virtual returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n\\n return true;\\n }\\n\\n function transfer(address to, uint256 amount) public virtual returns (bool) {\\n balanceOf[msg.sender] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(msg.sender, to, amount);\\n\\n return true;\\n }\\n\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual returns (bool) {\\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\\n\\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\\n\\n balanceOf[from] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n return true;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 LOGIC\\n //////////////////////////////////////////////////////////////*/\\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 ) public virtual {\\n require(deadline >= block.timestamp, \\\"PERMIT_DEADLINE_EXPIRED\\\");\\n\\n // Unchecked because the only math done is incrementing\\n // the owner's nonce which cannot realistically overflow.\\n unchecked {\\n address recoveredAddress = ecrecover(\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR(),\\n keccak256(\\n abi.encode(\\n keccak256(\\n \\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\"\\n ),\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n require(recoveredAddress != address(0) && recoveredAddress == owner, \\\"INVALID_SIGNER\\\");\\n\\n allowance[recoveredAddress][spender] = value;\\n }\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\\n }\\n\\n function computeDomainSeparator() internal view virtual returns (bytes32) {\\n return\\n keccak256(\\n abi.encode(\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"),\\n keccak256(bytes(name)),\\n keccak256(\\\"1\\\"),\\n block.chainid,\\n address(this)\\n )\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _mint(address to, uint256 amount) internal virtual {\\n totalSupply += amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(address(0), to, amount);\\n }\\n\\n function _burn(address from, uint256 amount) internal virtual {\\n balanceOf[from] -= amount;\\n\\n // Cannot underflow because a user's balance\\n // will never be larger than the total supply.\\n unchecked {\\n totalSupply -= amount;\\n }\\n\\n emit Transfer(from, address(0), amount);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/message/libraries/MessageSenderLib.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"../../interfaces/IBridge.sol\\\";\\nimport \\\"../../interfaces/IOriginalTokenVault.sol\\\";\\nimport \\\"../../interfaces/IOriginalTokenVaultV2.sol\\\";\\nimport \\\"../../interfaces/IPeggedTokenBridge.sol\\\";\\nimport \\\"../../interfaces/IPeggedTokenBridgeV2.sol\\\";\\nimport \\\"../interfaces/IMessageBus.sol\\\";\\nimport \\\"./MsgDataTypes.sol\\\";\\n\\nlibrary MessageSenderLib {\\n using SafeERC20 for IERC20;\\n\\n // ============== Internal library functions called by apps ==============\\n\\n /**\\n * @notice Sends a message to an app on another chain via MessageBus without an associated transfer.\\n * @param _receiver The address of the destination app contract.\\n * @param _dstChainId The destination chain ID.\\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\\n * @param _messageBus The address of the MessageBus on this chain.\\n * @param _fee The fee amount to pay to MessageBus.\\n */\\n function sendMessage(\\n address _receiver,\\n uint64 _dstChainId,\\n bytes memory _message,\\n address _messageBus,\\n uint256 _fee\\n ) internal {\\n IMessageBus(_messageBus).sendMessage{value: _fee}(_receiver, _dstChainId, _message);\\n }\\n\\n // Send message to non-evm chain with bytes for receiver address,\\n // otherwise same as above.\\n function sendMessage(\\n bytes calldata _receiver,\\n uint64 _dstChainId,\\n bytes memory _message,\\n address _messageBus,\\n uint256 _fee\\n ) internal {\\n IMessageBus(_messageBus).sendMessage{value: _fee}(_receiver, _dstChainId, _message);\\n }\\n\\n /**\\n * @notice Sends a message to an app on another chain via MessageBus with an associated transfer.\\n * @param _receiver The address of the destination app contract.\\n * @param _token The address of the token to be sent.\\n * @param _amount The amount of tokens to be sent.\\n * @param _dstChainId The destination chain ID.\\n * @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\\n * @param _maxSlippage The max slippage accepted, given as percentage in point (pip). Eg. 5000 means 0.5%.\\n * Must be greater than minimalMaxSlippage. Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount or the\\n * transfer can be refunded. Only applicable to the {MsgDataTypes.BridgeSendType.Liquidity}.\\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\\n * @param _bridgeSendType One of the {MsgDataTypes.BridgeSendType} enum.\\n * @param _messageBus The address of the MessageBus on this chain.\\n * @param _fee The fee amount to pay to MessageBus.\\n * @return The transfer ID.\\n */\\n function sendMessageWithTransfer(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce,\\n uint32 _maxSlippage,\\n bytes memory _message,\\n MsgDataTypes.BridgeSendType _bridgeSendType,\\n address _messageBus,\\n uint256 _fee\\n ) internal returns (bytes32) {\\n (bytes32 transferId, address bridge) = sendTokenTransfer(\\n _receiver,\\n _token,\\n _amount,\\n _dstChainId,\\n _nonce,\\n _maxSlippage,\\n _bridgeSendType,\\n _messageBus\\n );\\n if (_message.length > 0) {\\n IMessageBus(_messageBus).sendMessageWithTransfer{value: _fee}(\\n _receiver,\\n _dstChainId,\\n bridge,\\n transferId,\\n _message\\n );\\n }\\n return transferId;\\n }\\n\\n /**\\n * @notice Sends a token transfer via a bridge.\\n * @param _receiver The address of the destination app contract.\\n * @param _token The address of the token to be sent.\\n * @param _amount The amount of tokens to be sent.\\n * @param _dstChainId The destination chain ID.\\n * @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\\n * @param _maxSlippage The max slippage accepted, given as percentage in point (pip). Eg. 5000 means 0.5%.\\n * Must be greater than minimalMaxSlippage. Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount or the\\n * transfer can be refunded.\\n * @param _bridgeSendType One of the {MsgDataTypes.BridgeSendType} enum.\\n */\\n function sendTokenTransfer(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce,\\n uint32 _maxSlippage,\\n MsgDataTypes.BridgeSendType _bridgeSendType,\\n address _messageBus\\n ) internal returns (bytes32 transferId, address bridge) {\\n if (_bridgeSendType == MsgDataTypes.BridgeSendType.Liquidity) {\\n bridge = IMessageBus(_messageBus).liquidityBridge();\\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\\n IBridge(bridge).send(_receiver, _token, _amount, _dstChainId, _nonce, _maxSlippage);\\n transferId = computeLiqBridgeTransferId(_receiver, _token, _amount, _dstChainId, _nonce);\\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegDeposit) {\\n bridge = IMessageBus(_messageBus).pegVault();\\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\\n IOriginalTokenVault(bridge).deposit(_token, _amount, _dstChainId, _receiver, _nonce);\\n transferId = computePegV1DepositId(_receiver, _token, _amount, _dstChainId, _nonce);\\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegBurn) {\\n bridge = IMessageBus(_messageBus).pegBridge();\\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\\n IPeggedTokenBridge(bridge).burn(_token, _amount, _receiver, _nonce);\\n // handle cases where certain tokens do not spend allowance for role-based burn\\n IERC20(_token).safeApprove(bridge, 0);\\n transferId = computePegV1BurnId(_receiver, _token, _amount, _nonce);\\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2Deposit) {\\n bridge = IMessageBus(_messageBus).pegVaultV2();\\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\\n transferId = IOriginalTokenVaultV2(bridge).deposit(_token, _amount, _dstChainId, _receiver, _nonce);\\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2Burn) {\\n bridge = IMessageBus(_messageBus).pegBridgeV2();\\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\\n transferId = IPeggedTokenBridgeV2(bridge).burn(_token, _amount, _dstChainId, _receiver, _nonce);\\n // handle cases where certain tokens do not spend allowance for role-based burn\\n IERC20(_token).safeApprove(bridge, 0);\\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2BurnFrom) {\\n bridge = IMessageBus(_messageBus).pegBridgeV2();\\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\\n transferId = IPeggedTokenBridgeV2(bridge).burnFrom(_token, _amount, _dstChainId, _receiver, _nonce);\\n // handle cases where certain tokens do not spend allowance for role-based burn\\n IERC20(_token).safeApprove(bridge, 0);\\n } else {\\n revert(\\\"bridge type not supported\\\");\\n }\\n }\\n\\n function computeLiqBridgeTransferId(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce\\n ) internal view returns (bytes32) {\\n return\\n keccak256(\\n abi.encodePacked(address(this), _receiver, _token, _amount, _dstChainId, _nonce, uint64(block.chainid))\\n );\\n }\\n\\n function computePegV1DepositId(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce\\n ) internal view returns (bytes32) {\\n return\\n keccak256(\\n abi.encodePacked(address(this), _token, _amount, _dstChainId, _receiver, _nonce, uint64(block.chainid))\\n );\\n }\\n\\n function computePegV1BurnId(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _nonce\\n ) internal view returns (bytes32) {\\n return keccak256(abi.encodePacked(address(this), _token, _amount, _receiver, _nonce, uint64(block.chainid)));\\n }\\n}\\n\"\r\n },\r\n \"src/Periphery/RelayerCelerIM.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IERC20, SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { ContractCallNotAllowed, ExternalCallFailed, InvalidConfig, UnAuthorized, WithdrawFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { PeripheryRegistryFacet } from \\\"../Facets/PeripheryRegistryFacet.sol\\\";\\nimport { IExecutor } from \\\"../Interfaces/IExecutor.sol\\\";\\nimport { TransferrableOwnership } from \\\"../Helpers/TransferrableOwnership.sol\\\";\\nimport { IMessageReceiverApp } from \\\"celer-network/contracts/message/interfaces/IMessageReceiverApp.sol\\\";\\nimport { CelerIM } from \\\"lifi/Helpers/CelerIMFacetBase.sol\\\";\\nimport { MessageSenderLib, MsgDataTypes, IMessageBus, IOriginalTokenVault, IPeggedTokenBridge, IOriginalTokenVaultV2, IPeggedTokenBridgeV2 } from \\\"celer-network/contracts/message/libraries/MessageSenderLib.sol\\\";\\nimport { IBridge as ICBridge } from \\\"celer-network/contracts/interfaces/IBridge.sol\\\";\\n\\n/// @title RelayerCelerIM\\n/// @author LI.FI (https://li.fi)\\n/// @notice Relayer contract for CelerIM that forwards calls and handles refunds on src side and acts receiver on dest\\n/// @custom:version 2.0.0\\ncontract RelayerCelerIM is ILiFi, TransferrableOwnership {\\n using SafeERC20 for IERC20;\\n\\n /// Storage ///\\n\\n IMessageBus public cBridgeMessageBus;\\n address public diamondAddress;\\n\\n /// Events ///\\n\\n event LogWithdraw(\\n address indexed _assetAddress,\\n address indexed _to,\\n uint256 amount\\n );\\n\\n /// Modifiers ///\\n\\n modifier onlyCBridgeMessageBus() {\\n if (msg.sender != address(cBridgeMessageBus)) revert UnAuthorized();\\n _;\\n }\\n modifier onlyDiamond() {\\n if (msg.sender != diamondAddress) revert UnAuthorized();\\n _;\\n }\\n\\n /// Constructor\\n\\n constructor(\\n address _cBridgeMessageBusAddress,\\n address _owner,\\n address _diamondAddress\\n ) TransferrableOwnership(_owner) {\\n owner = _owner;\\n cBridgeMessageBus = IMessageBus(_cBridgeMessageBusAddress);\\n diamondAddress = _diamondAddress;\\n }\\n\\n /// External Methods ///\\n\\n /**\\n * @notice Called by MessageBus to execute a message with an associated token transfer.\\n * The Receiver is guaranteed to have received the right amount of tokens before this function is called.\\n * @param * (unused) The address of the source app contract\\n * @param _token The address of the token that comes out of the bridge\\n * @param _amount The amount of tokens received at this contract through the cross-chain bridge.\\n * @param * (unused) The source chain ID where the transfer is originated from\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param * (unused) Address who called the MessageBus execution function\\n */\\n function executeMessageWithTransfer(\\n address,\\n address _token,\\n uint256 _amount,\\n uint64,\\n bytes calldata _message,\\n address\\n )\\n external\\n payable\\n onlyCBridgeMessageBus\\n returns (IMessageReceiverApp.ExecutionStatus)\\n {\\n // decode message\\n (\\n bytes32 transactionId,\\n LibSwap.SwapData[] memory swapData,\\n address receiver,\\n address refundAddress\\n ) = abi.decode(\\n _message,\\n (bytes32, LibSwap.SwapData[], address, address)\\n );\\n\\n _swapAndCompleteBridgeTokens(\\n transactionId,\\n swapData,\\n _token,\\n payable(receiver),\\n _amount,\\n refundAddress\\n );\\n\\n return IMessageReceiverApp.ExecutionStatus.Success;\\n }\\n\\n /**\\n * @notice Called by MessageBus to process refund of the original transfer from this contract.\\n * The contract is guaranteed to have received the refund before this function is called.\\n * @param _token The token address of the original transfer\\n * @param _amount The amount of the original transfer\\n * @param _message The same message associated with the original transfer\\n * @param * (unused) Address who called the MessageBus execution function\\n */\\n function executeMessageWithTransferRefund(\\n address _token,\\n uint256 _amount,\\n bytes calldata _message,\\n address\\n )\\n external\\n payable\\n onlyCBridgeMessageBus\\n returns (IMessageReceiverApp.ExecutionStatus)\\n {\\n (bytes32 transactionId, , , address refundAddress) = abi.decode(\\n _message,\\n (bytes32, LibSwap.SwapData[], address, address)\\n );\\n\\n // return funds to cBridgeData.refundAddress\\n LibAsset.transferAsset(_token, payable(refundAddress), _amount);\\n\\n emit LiFiTransferRecovered(\\n transactionId,\\n _token,\\n refundAddress,\\n _amount,\\n block.timestamp\\n );\\n\\n return IMessageReceiverApp.ExecutionStatus.Success;\\n }\\n\\n /**\\n * @notice Forwards a call to transfer tokens to cBridge (sent via this contract to ensure that potential refunds are sent here)\\n * @param _bridgeData the core information needed for bridging\\n * @param _celerIMData data specific to CelerIM\\n */\\n // solhint-disable-next-line code-complexity\\n function sendTokenTransfer(\\n ILiFi.BridgeData memory _bridgeData,\\n CelerIM.CelerIMData calldata _celerIMData\\n )\\n external\\n payable\\n onlyDiamond\\n returns (bytes32 transferId, address bridgeAddress)\\n {\\n // approve to and call correct bridge depending on BridgeSendType\\n // @dev copied and slightly adapted from Celer MessageSenderLib\\n if (_celerIMData.bridgeType == MsgDataTypes.BridgeSendType.Liquidity) {\\n bridgeAddress = cBridgeMessageBus.liquidityBridge();\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // case: native asset bridging\\n ICBridge(bridgeAddress).sendNative{\\n value: _bridgeData.minAmount\\n }(\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _celerIMData.nonce,\\n _celerIMData.maxSlippage\\n );\\n } else {\\n // case: ERC20 asset bridging\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n bridgeAddress,\\n _bridgeData.minAmount\\n );\\n // solhint-disable-next-line check-send-result\\n ICBridge(bridgeAddress).send(\\n _bridgeData.receiver,\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _celerIMData.nonce,\\n _celerIMData.maxSlippage\\n );\\n }\\n transferId = MessageSenderLib.computeLiqBridgeTransferId(\\n _bridgeData.receiver,\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _celerIMData.nonce\\n );\\n } else if (\\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegDeposit\\n ) {\\n bridgeAddress = cBridgeMessageBus.pegVault();\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n bridgeAddress,\\n _bridgeData.minAmount\\n );\\n IOriginalTokenVault(bridgeAddress).deposit(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _bridgeData.receiver,\\n _celerIMData.nonce\\n );\\n transferId = MessageSenderLib.computePegV1DepositId(\\n _bridgeData.receiver,\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _celerIMData.nonce\\n );\\n } else if (\\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegBurn\\n ) {\\n bridgeAddress = cBridgeMessageBus.pegBridge();\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n bridgeAddress,\\n _bridgeData.minAmount\\n );\\n IPeggedTokenBridge(bridgeAddress).burn(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n _bridgeData.receiver,\\n _celerIMData.nonce\\n );\\n transferId = MessageSenderLib.computePegV1BurnId(\\n _bridgeData.receiver,\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n _celerIMData.nonce\\n );\\n } else if (\\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegV2Deposit\\n ) {\\n bridgeAddress = cBridgeMessageBus.pegVaultV2();\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // case: native asset bridging\\n transferId = IOriginalTokenVaultV2(bridgeAddress)\\n .depositNative{ value: _bridgeData.minAmount }(\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _bridgeData.receiver,\\n _celerIMData.nonce\\n );\\n } else {\\n // case: ERC20 bridging\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n bridgeAddress,\\n _bridgeData.minAmount\\n );\\n transferId = IOriginalTokenVaultV2(bridgeAddress).deposit(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _bridgeData.receiver,\\n _celerIMData.nonce\\n );\\n }\\n } else if (\\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegV2Burn\\n ) {\\n bridgeAddress = cBridgeMessageBus.pegBridgeV2();\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n bridgeAddress,\\n _bridgeData.minAmount\\n );\\n transferId = IPeggedTokenBridgeV2(bridgeAddress).burn(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _bridgeData.receiver,\\n _celerIMData.nonce\\n );\\n } else if (\\n _celerIMData.bridgeType ==\\n MsgDataTypes.BridgeSendType.PegV2BurnFrom\\n ) {\\n bridgeAddress = cBridgeMessageBus.pegBridgeV2();\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n bridgeAddress,\\n _bridgeData.minAmount\\n );\\n transferId = IPeggedTokenBridgeV2(bridgeAddress).burnFrom(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _bridgeData.receiver,\\n _celerIMData.nonce\\n );\\n } else {\\n revert InvalidConfig();\\n }\\n }\\n\\n /**\\n * @notice Forwards a call to the CBridge Messagebus\\n * @param _receiver The address of the destination app contract.\\n * @param _dstChainId The destination chain ID.\\n * @param _srcBridge The bridge contract to send the transfer with.\\n * @param _srcTransferId The transfer ID.\\n * @param _dstChainId The destination chain ID.\\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\\n */\\n function forwardSendMessageWithTransfer(\\n address _receiver,\\n uint256 _dstChainId,\\n address _srcBridge,\\n bytes32 _srcTransferId,\\n bytes calldata _message\\n ) external payable onlyDiamond {\\n cBridgeMessageBus.sendMessageWithTransfer{ value: msg.value }(\\n _receiver,\\n _dstChainId,\\n _srcBridge,\\n _srcTransferId,\\n _message\\n );\\n }\\n\\n // ------------------------------------------------------------------------------------------------\\n\\n /// Private Methods ///\\n\\n /// @notice Performs a swap before completing a cross-chain transaction\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swapData array of data needed for swaps\\n /// @param assetId token received from the other chain\\n /// @param receiver address that will receive tokens in the end\\n /// @param amount amount of token\\n function _swapAndCompleteBridgeTokens(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] memory _swapData,\\n address assetId,\\n address payable receiver,\\n uint256 amount,\\n address refundAddress\\n ) private {\\n bool success;\\n IExecutor executor = IExecutor(\\n PeripheryRegistryFacet(diamondAddress).getPeripheryContract(\\n \\\"Executor\\\"\\n )\\n );\\n if (LibAsset.isNativeAsset(assetId)) {\\n try\\n executor.swapAndCompleteBridgeTokens{ value: amount }(\\n _transactionId,\\n _swapData,\\n assetId,\\n receiver\\n )\\n {\\n success = true;\\n } catch {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool fundsSent, ) = refundAddress.call{ value: amount }(\\\"\\\");\\n if (!fundsSent) {\\n revert ExternalCallFailed();\\n }\\n }\\n } else {\\n IERC20 token = IERC20(assetId);\\n token.safeApprove(address(executor), 0);\\n token.safeIncreaseAllowance(address(executor), amount);\\n\\n try\\n executor.swapAndCompleteBridgeTokens(\\n _transactionId,\\n _swapData,\\n assetId,\\n receiver\\n )\\n {\\n success = true;\\n } catch {\\n token.safeTransfer(refundAddress, amount);\\n }\\n token.safeApprove(address(executor), 0);\\n }\\n\\n if (!success) {\\n emit LiFiTransferRecovered(\\n _transactionId,\\n assetId,\\n refundAddress,\\n amount,\\n block.timestamp\\n );\\n }\\n }\\n\\n /// @notice Sends remaining token to given receiver address (for refund cases)\\n /// @param assetId Address of the token to be withdrawn\\n /// @param receiver Address that will receive tokens\\n /// @param amount Amount of tokens to be withdrawn\\n function withdraw(\\n address assetId,\\n address payable receiver,\\n uint256 amount\\n ) external onlyOwner {\\n if (LibAsset.isNativeAsset(assetId)) {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = receiver.call{ value: amount }(\\\"\\\");\\n if (!success) {\\n revert WithdrawFailed();\\n }\\n } else {\\n IERC20(assetId).safeTransfer(receiver, amount);\\n }\\n emit LogWithdraw(assetId, receiver, amount);\\n }\\n\\n /// @notice Triggers a cBridge refund with calldata produced by cBridge API\\n /// @param _callTo The address to execute the calldata on\\n /// @param _callData The data to execute\\n /// @param _assetAddress Asset to be withdrawn\\n /// @param _to Address to withdraw to\\n /// @param _amount Amount of asset to withdraw\\n function triggerRefund(\\n address payable _callTo,\\n bytes calldata _callData,\\n address _assetAddress,\\n address _to,\\n uint256 _amount\\n ) external onlyOwner {\\n bool success;\\n\\n // make sure that callTo address is either of the cBridge addresses\\n if (\\n cBridgeMessageBus.liquidityBridge() != _callTo &&\\n cBridgeMessageBus.pegBridge() != _callTo &&\\n cBridgeMessageBus.pegBridgeV2() != _callTo &&\\n cBridgeMessageBus.pegVault() != _callTo &&\\n cBridgeMessageBus.pegVaultV2() != _callTo\\n ) {\\n revert ContractCallNotAllowed();\\n }\\n\\n // call contract\\n // solhint-disable-next-line avoid-low-level-calls\\n (success, ) = _callTo.call(_callData);\\n\\n // forward funds to _to address and emit event, if cBridge refund successful\\n if (success) {\\n address sendTo = (LibUtil.isZeroAddress(_to)) ? msg.sender : _to;\\n LibAsset.transferAsset(_assetAddress, payable(sendTo), _amount);\\n emit LogWithdraw(_assetAddress, sendTo, _amount);\\n } else {\\n revert WithdrawFailed();\\n }\\n }\\n\\n // required in order to receive native tokens from cBridge facet\\n // solhint-disable-next-line no-empty-blocks\\n receive() external payable {}\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/interfaces/IBridge.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\ninterface IBridge {\\n function send(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce,\\n uint32 _maxSlippage\\n ) external;\\n\\n function sendNative(\\n address _receiver,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce,\\n uint32 _maxSlippage\\n ) external payable;\\n\\n function relay(\\n bytes calldata _relayRequest,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external;\\n\\n function transfers(bytes32 transferId) external view returns (bool);\\n\\n function withdraws(bytes32 withdrawId) external view returns (bool);\\n\\n function withdraw(\\n bytes calldata _wdmsg,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external;\\n\\n /**\\n * @notice Verifies that a message is signed by a quorum among the signers.\\n * @param _msg signed message\\n * @param _sigs list of signatures sorted by signer addresses in ascending order\\n * @param _signers sorted list of current signers\\n * @param _powers powers of current signers\\n */\\n function verifySigs(\\n bytes memory _msg,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external view;\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/interfaces/IOriginalTokenVault.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\ninterface IOriginalTokenVault {\\n /**\\n * @notice Lock original tokens to trigger mint at a remote chain's PeggedTokenBridge\\n * @param _token local token address\\n * @param _amount locked token amount\\n * @param _mintChainId destination chainId to mint tokens\\n * @param _mintAccount destination account to receive minted tokens\\n * @param _nonce user input to guarantee unique depositId\\n */\\n function deposit(\\n address _token,\\n uint256 _amount,\\n uint64 _mintChainId,\\n address _mintAccount,\\n uint64 _nonce\\n ) external;\\n\\n /**\\n * @notice Lock native token as original token to trigger mint at a remote chain's PeggedTokenBridge\\n * @param _amount locked token amount\\n * @param _mintChainId destination chainId to mint tokens\\n * @param _mintAccount destination account to receive minted tokens\\n * @param _nonce user input to guarantee unique depositId\\n */\\n function depositNative(\\n uint256 _amount,\\n uint64 _mintChainId,\\n address _mintAccount,\\n uint64 _nonce\\n ) external payable;\\n\\n /**\\n * @notice Withdraw locked original tokens triggered by a burn at a remote chain's PeggedTokenBridge.\\n * @param _request The serialized Withdraw protobuf.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the bridge's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function withdraw(\\n bytes calldata _request,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external;\\n\\n function records(bytes32 recordId) external view returns (bool);\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/interfaces/IOriginalTokenVaultV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\ninterface IOriginalTokenVaultV2 {\\n /**\\n * @notice Lock original tokens to trigger mint at a remote chain's PeggedTokenBridge\\n * @param _token local token address\\n * @param _amount locked token amount\\n * @param _mintChainId destination chainId to mint tokens\\n * @param _mintAccount destination account to receive minted tokens\\n * @param _nonce user input to guarantee unique depositId\\n */\\n function deposit(\\n address _token,\\n uint256 _amount,\\n uint64 _mintChainId,\\n address _mintAccount,\\n uint64 _nonce\\n ) external returns (bytes32);\\n\\n /**\\n * @notice Lock native token as original token to trigger mint at a remote chain's PeggedTokenBridge\\n * @param _amount locked token amount\\n * @param _mintChainId destination chainId to mint tokens\\n * @param _mintAccount destination account to receive minted tokens\\n * @param _nonce user input to guarantee unique depositId\\n */\\n function depositNative(\\n uint256 _amount,\\n uint64 _mintChainId,\\n address _mintAccount,\\n uint64 _nonce\\n ) external payable returns (bytes32);\\n\\n /**\\n * @notice Withdraw locked original tokens triggered by a burn at a remote chain's PeggedTokenBridge.\\n * @param _request The serialized Withdraw protobuf.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the bridge's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function withdraw(\\n bytes calldata _request,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external returns (bytes32);\\n\\n function records(bytes32 recordId) external view returns (bool);\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/interfaces/IPeggedTokenBridge.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\ninterface IPeggedTokenBridge {\\n /**\\n * @notice Burn tokens to trigger withdrawal at a remote chain's OriginalTokenVault\\n * @param _token local token address\\n * @param _amount locked token amount\\n * @param _withdrawAccount account who withdraw original tokens on the remote chain\\n * @param _nonce user input to guarantee unique depositId\\n */\\n function burn(\\n address _token,\\n uint256 _amount,\\n address _withdrawAccount,\\n uint64 _nonce\\n ) external;\\n\\n /**\\n * @notice Mint tokens triggered by deposit at a remote chain's OriginalTokenVault.\\n * @param _request The serialized Mint protobuf.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the sigsVerifier's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function mint(\\n bytes calldata _request,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external;\\n\\n function records(bytes32 recordId) external view returns (bool);\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/interfaces/IPeggedTokenBridgeV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\ninterface IPeggedTokenBridgeV2 {\\n /**\\n * @notice Burn pegged tokens to trigger a cross-chain withdrawal of the original tokens at a remote chain's\\n * OriginalTokenVault, or mint at another remote chain\\n * @param _token The pegged token address.\\n * @param _amount The amount to burn.\\n * @param _toChainId If zero, withdraw from original vault; otherwise, the remote chain to mint tokens.\\n * @param _toAccount The account to receive tokens on the remote chain\\n * @param _nonce A number to guarantee unique depositId. Can be timestamp in practice.\\n */\\n function burn(\\n address _token,\\n uint256 _amount,\\n uint64 _toChainId,\\n address _toAccount,\\n uint64 _nonce\\n ) external returns (bytes32);\\n\\n // same with `burn` above, use openzeppelin ERC20Burnable interface\\n function burnFrom(\\n address _token,\\n uint256 _amount,\\n uint64 _toChainId,\\n address _toAccount,\\n uint64 _nonce\\n ) external returns (bytes32);\\n\\n /**\\n * @notice Mint tokens triggered by deposit at a remote chain's OriginalTokenVault.\\n * @param _request The serialized Mint protobuf.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the sigsVerifier's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function mint(\\n bytes calldata _request,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external returns (bytes32);\\n\\n function records(bytes32 recordId) external view returns (bool);\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/message/interfaces/IMessageBus.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\nimport \\\"../libraries/MsgDataTypes.sol\\\";\\n\\ninterface IMessageBus {\\n /**\\n * @notice Send a message to a contract on another chain.\\n * Sender needs to make sure the uniqueness of the message Id, which is computed as\\n * hash(type.MessageOnly, sender, receiver, srcChainId, srcTxHash, dstChainId, message).\\n * If messages with the same Id are sent, only one of them will succeed at dst chain..\\n * A fee is charged in the native gas token.\\n * @param _receiver The address of the destination app contract.\\n * @param _dstChainId The destination chain ID.\\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\\n */\\n function sendMessage(\\n address _receiver,\\n uint256 _dstChainId,\\n bytes calldata _message\\n ) external payable;\\n\\n // same as above, except that receiver is an non-evm chain address,\\n function sendMessage(\\n bytes calldata _receiver,\\n uint256 _dstChainId,\\n bytes calldata _message\\n ) external payable;\\n\\n /**\\n * @notice Send a message associated with a token transfer to a contract on another chain.\\n * If messages with the same srcTransferId are sent, only one of them will succeed at dst chain..\\n * A fee is charged in the native token.\\n * @param _receiver The address of the destination app contract.\\n * @param _dstChainId The destination chain ID.\\n * @param _srcBridge The bridge contract to send the transfer with.\\n * @param _srcTransferId The transfer ID.\\n * @param _dstChainId The destination chain ID.\\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\\n */\\n function sendMessageWithTransfer(\\n address _receiver,\\n uint256 _dstChainId,\\n address _srcBridge,\\n bytes32 _srcTransferId,\\n bytes calldata _message\\n ) external payable;\\n\\n /**\\n * @notice Execute a message not associated with a transfer.\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the sigsVerifier's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function executeMessage(\\n bytes calldata _message,\\n MsgDataTypes.RouteInfo calldata _route,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external payable;\\n\\n /**\\n * @notice Execute a message with a successful transfer.\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param _transfer The transfer info.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the sigsVerifier's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function executeMessageWithTransfer(\\n bytes calldata _message,\\n MsgDataTypes.TransferInfo calldata _transfer,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external payable;\\n\\n /**\\n * @notice Execute a message with a refunded transfer.\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param _transfer The transfer info.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the sigsVerifier's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function executeMessageWithTransferRefund(\\n bytes calldata _message, // the same message associated with the original transfer\\n MsgDataTypes.TransferInfo calldata _transfer,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external payable;\\n\\n /**\\n * @notice Withdraws message fee in the form of native gas token.\\n * @param _account The address receiving the fee.\\n * @param _cumulativeFee The cumulative fee credited to the account. Tracked by SGN.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A withdrawal must be\\n * signed-off by +2/3 of the sigsVerifier's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function withdrawFee(\\n address _account,\\n uint256 _cumulativeFee,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external;\\n\\n /**\\n * @notice Calculates the required fee for the message.\\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\\n @ @return The required fee.\\n */\\n function calcFee(bytes calldata _message) external view returns (uint256);\\n\\n function liquidityBridge() external view returns (address);\\n\\n function pegBridge() external view returns (address);\\n\\n function pegBridgeV2() external view returns (address);\\n\\n function pegVault() external view returns (address);\\n\\n function pegVaultV2() external view returns (address);\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/message/libraries/MsgDataTypes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\nlibrary MsgDataTypes {\\n string constant ABORT_PREFIX = \\\"MSG::ABORT:\\\";\\n\\n // bridge operation type at the sender side (src chain)\\n enum BridgeSendType {\\n Null,\\n Liquidity,\\n PegDeposit,\\n PegBurn,\\n PegV2Deposit,\\n PegV2Burn,\\n PegV2BurnFrom\\n }\\n\\n // bridge operation type at the receiver side (dst chain)\\n enum TransferType {\\n Null,\\n LqRelay, // relay through liquidity bridge\\n LqWithdraw, // withdraw from liquidity bridge\\n PegMint, // mint through pegged token bridge\\n PegWithdraw, // withdraw from original token vault\\n PegV2Mint, // mint through pegged token bridge v2\\n PegV2Withdraw // withdraw from original token vault v2\\n }\\n\\n enum MsgType {\\n MessageWithTransfer,\\n MessageOnly\\n }\\n\\n enum TxStatus {\\n Null,\\n Success,\\n Fail,\\n Fallback,\\n Pending // transient state within a transaction\\n }\\n\\n struct TransferInfo {\\n TransferType t;\\n address sender;\\n address receiver;\\n address token;\\n uint256 amount;\\n uint64 wdseq; // only needed for LqWithdraw (refund)\\n uint64 srcChainId;\\n bytes32 refId;\\n bytes32 srcTxHash; // src chain msg tx hash\\n }\\n\\n struct RouteInfo {\\n address sender;\\n address receiver;\\n uint64 srcChainId;\\n bytes32 srcTxHash; // src chain msg tx hash\\n }\\n\\n // used for msg from non-evm chains with longer-bytes address\\n struct RouteInfo2 {\\n bytes sender;\\n address receiver;\\n uint64 srcChainId;\\n bytes32 srcTxHash;\\n }\\n\\n // combination of RouteInfo and RouteInfo2 for easier processing\\n struct Route {\\n address sender; // from RouteInfo\\n bytes senderBytes; // from RouteInfo2\\n address receiver;\\n uint64 srcChainId;\\n bytes32 srcTxHash;\\n }\\n\\n struct MsgWithTransferExecutionParams {\\n bytes message;\\n TransferInfo transfer;\\n bytes[] sigs;\\n address[] signers;\\n uint256[] powers;\\n }\\n\\n struct BridgeTransferParams {\\n bytes request;\\n bytes[] sigs;\\n address[] signers;\\n uint256[] powers;\\n }\\n}\\n\"\r\n },\r\n \"src/Facets/PeripheryRegistryFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\n\\n/// @title Periphery Registry Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice A simple registry to track LIFI periphery contracts\\n/// @custom:version 1.0.0\\ncontract PeripheryRegistryFacet {\\n /// Storage ///\\n\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.facets.periphery_registry\\\");\\n\\n /// Types ///\\n\\n struct Storage {\\n mapping(string => address) contracts;\\n }\\n\\n /// Events ///\\n\\n event PeripheryContractRegistered(string name, address contractAddress);\\n\\n /// External Methods ///\\n\\n /// @notice Registers a periphery contract address with a specified name\\n /// @param _name the name to register the contract address under\\n /// @param _contractAddress the address of the contract to register\\n function registerPeripheryContract(\\n string calldata _name,\\n address _contractAddress\\n ) external {\\n LibDiamond.enforceIsContractOwner();\\n Storage storage s = getStorage();\\n s.contracts[_name] = _contractAddress;\\n emit PeripheryContractRegistered(_name, _contractAddress);\\n }\\n\\n /// @notice Returns the registered contract address by its name\\n /// @param _name the registered name of the contract\\n function getPeripheryContract(\\n string calldata _name\\n ) external view returns (address) {\\n return getStorage().contracts[_name];\\n }\\n\\n /// @dev fetch local storage\\n function getStorage() private pure returns (Storage storage s) {\\n bytes32 namespace = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n s.slot := namespace\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IExecutor.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\n/// @title Interface for Executor\\n/// @author LI.FI (https://li.fi)\\ninterface IExecutor {\\n /// @notice Performs a swap before completing a cross-chain transaction\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swapData array of data needed for swaps\\n /// @param transferredAssetId token received from the other chain\\n /// @param receiver address that will receive tokens in the end\\n function swapAndCompleteBridgeTokens(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swapData,\\n address transferredAssetId,\\n address payable receiver\\n ) external payable;\\n}\\n\"\r\n },\r\n \"src/Helpers/TransferrableOwnership.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IERC173 } from \\\"../Interfaces/IERC173.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\n\\ncontract TransferrableOwnership is IERC173 {\\n address public owner;\\n address public pendingOwner;\\n\\n /// Errors ///\\n error UnAuthorized();\\n error NoNullOwner();\\n error NewOwnerMustNotBeSelf();\\n error NoPendingOwnershipTransfer();\\n error NotPendingOwner();\\n\\n /// Events ///\\n event OwnershipTransferRequested(\\n address indexed _from,\\n address indexed _to\\n );\\n\\n constructor(address initialOwner) {\\n owner = initialOwner;\\n }\\n\\n modifier onlyOwner() {\\n if (msg.sender != owner) revert UnAuthorized();\\n _;\\n }\\n\\n /// @notice Initiates transfer of ownership to a new address\\n /// @param _newOwner the address to transfer ownership to\\n function transferOwnership(address _newOwner) external onlyOwner {\\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\\n pendingOwner = _newOwner;\\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\\n }\\n\\n /// @notice Cancel transfer of ownership\\n function cancelOwnershipTransfer() external onlyOwner {\\n if (pendingOwner == LibAsset.NULL_ADDRESS)\\n revert NoPendingOwnershipTransfer();\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n\\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\\n function confirmOwnershipTransfer() external {\\n address _pendingOwner = pendingOwner;\\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\\n emit OwnershipTransferred(owner, _pendingOwner);\\n owner = _pendingOwner;\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/message/interfaces/IMessageReceiverApp.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\ninterface IMessageReceiverApp {\\n enum ExecutionStatus {\\n Fail, // execution failed, finalized\\n Success, // execution succeeded, finalized\\n Retry // execution rejected, can retry later\\n }\\n\\n /**\\n * @notice Called by MessageBus to execute a message\\n * @param _sender The address of the source app contract\\n * @param _srcChainId The source chain ID where the transfer is originated from\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param _executor Address who called the MessageBus execution function\\n */\\n function executeMessage(\\n address _sender,\\n uint64 _srcChainId,\\n bytes calldata _message,\\n address _executor\\n ) external payable returns (ExecutionStatus);\\n\\n // same as above, except that sender is an non-evm chain address,\\n // otherwise same as above.\\n function executeMessage(\\n bytes calldata _sender,\\n uint64 _srcChainId,\\n bytes calldata _message,\\n address _executor\\n ) external payable returns (ExecutionStatus);\\n\\n /**\\n * @notice Called by MessageBus to execute a message with an associated token transfer.\\n * The contract is guaranteed to have received the right amount of tokens before this function is called.\\n * @param _sender The address of the source app contract\\n * @param _token The address of the token that comes out of the bridge\\n * @param _amount The amount of tokens received at this contract through the cross-chain bridge.\\n * @param _srcChainId The source chain ID where the transfer is originated from\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param _executor Address who called the MessageBus execution function\\n */\\n function executeMessageWithTransfer(\\n address _sender,\\n address _token,\\n uint256 _amount,\\n uint64 _srcChainId,\\n bytes calldata _message,\\n address _executor\\n ) external payable returns (ExecutionStatus);\\n\\n /**\\n * @notice Only called by MessageBus if\\n * 1. executeMessageWithTransfer reverts, or\\n * 2. executeMessageWithTransfer returns ExecutionStatus.Fail\\n * The contract is guaranteed to have received the right amount of tokens before this function is called.\\n * @param _sender The address of the source app contract\\n * @param _token The address of the token that comes out of the bridge\\n * @param _amount The amount of tokens received at this contract through the cross-chain bridge.\\n * @param _srcChainId The source chain ID where the transfer is originated from\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param _executor Address who called the MessageBus execution function\\n */\\n function executeMessageWithTransferFallback(\\n address _sender,\\n address _token,\\n uint256 _amount,\\n uint64 _srcChainId,\\n bytes calldata _message,\\n address _executor\\n ) external payable returns (ExecutionStatus);\\n\\n /**\\n * @notice Called by MessageBus to process refund of the original transfer from this contract.\\n * The contract is guaranteed to have received the refund before this function is called.\\n * @param _token The token address of the original transfer\\n * @param _amount The amount of the original transfer\\n * @param _message The same message associated with the original transfer\\n * @param _executor Address who called the MessageBus execution function\\n */\\n function executeMessageWithTransferRefund(\\n address _token,\\n uint256 _amount,\\n bytes calldata _message,\\n address _executor\\n ) external payable returns (ExecutionStatus);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IERC173.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\n/// @title ERC-173 Contract Ownership Standard\\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\\n/* is ERC165 */\\ninterface IERC173 {\\n /// @dev This emits when ownership of a contract changes.\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n /// @notice Get the address of the owner\\n /// @return owner_ The address of the owner.\\n function owner() external view returns (address owner_);\\n\\n /// @notice Set the address of the new owner of the contract\\n /// @dev Set _newOwner to address(0) to renounce any ownership.\\n /// @param _newOwner The address of the new owner of the contract\\n function transferOwnership(address _newOwner) external;\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IMessageBus\",\"name\":\"_messageBus\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_relayerOwner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_diamondAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_cfUSDC\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"relayer\",\"outputs\":[{\"internalType\":\"contract RelayerCelerIM\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSlippage\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"callTo\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"messageBusFee\",\"type\":\"uint256\"},{\"internalType\":\"enum MsgDataTypes.BridgeSendType\",\"name\":\"bridgeType\",\"type\":\"uint8\"}],\"internalType\":\"struct CelerIM.CelerIMData\",\"name\":\"_celerIMData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaCelerIM\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSlippage\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"callTo\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"messageBusFee\",\"type\":\"uint256\"},{\"internalType\":\"enum MsgDataTypes.BridgeSendType\",\"name\":\"bridgeType\",\"type\":\"uint8\"}],\"internalType\":\"struct CelerIM.CelerIMData\",\"name\":\"_celerIMData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaCelerIM\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "CelerIMFacetMutable", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000004066d196a423b2b3b8b054f4f40efb47a74e200c000000000000000000000000156cebba59deb2cb23742f70dcb0a11cc775591f0000000000000000000000001231deb6f5749ef6ce6943a275a1d3e7486f4eae000000000000000000000000317f8d18fb16e49a958becd0ea72f8e153d25654", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/CelerIMFacetMutable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { CelerIMFacetBase, IMessageBus, MsgDataTypes, IERC20, CelerIM } from \"../Helpers/CelerIMFacetBase.sol\";\n\n/// @title CelerIMFacetMutable\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging tokens and data through CBridge\n/// @notice This contract is exclusively used for mutable diamond contracts\n/// @custom:version 2.0.0\ncontract CelerIMFacetMutable is CelerIMFacetBase {\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _messageBus The contract address of the cBridge Message Bus\n /// @param _relayerOwner The address that will become the owner of the RelayerCelerIM contract\n /// @param _diamondAddress The address of the diamond contract that will be connected with the RelayerCelerIM\n /// @param _cfUSDC The contract address of the Celer Flow USDC\n constructor(\n IMessageBus _messageBus,\n address _relayerOwner,\n address _diamondAddress,\n address _cfUSDC\n ) CelerIMFacetBase(_messageBus, _relayerOwner, _diamondAddress, _cfUSDC) {}\n}\n" + }, + "src/Helpers/CelerIMFacetBase.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ERC20 } from \"solmate/tokens/ERC20.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { InvalidAmount, InformationMismatch } from \"../Errors/GenericErrors.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { MessageSenderLib, MsgDataTypes, IMessageBus } from \"celer-network/contracts/message/libraries/MessageSenderLib.sol\";\nimport { RelayerCelerIM } from \"lifi/Periphery/RelayerCelerIM.sol\";\n\ninterface CelerToken {\n function canonical() external returns (address);\n}\n\ninterface CelerIM {\n /// @param maxSlippage The max slippage accepted, given as percentage in point (pip).\n /// @param nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\n /// @param callTo The address of the contract to be called at destination.\n /// @param callData The encoded calldata with below data\n /// bytes32 transactionId,\n /// LibSwap.SwapData[] memory swapData,\n /// address receiver,\n /// address refundAddress\n /// @param messageBusFee The fee to be paid to CBridge message bus for relaying the message\n /// @param bridgeType Defines the bridge operation type (must be one of the values of CBridge library MsgDataTypes.BridgeSendType)\n struct CelerIMData {\n uint32 maxSlippage;\n uint64 nonce;\n bytes callTo;\n bytes callData;\n uint256 messageBusFee;\n MsgDataTypes.BridgeSendType bridgeType;\n }\n}\n\n/// @title CelerIM Facet Base\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging tokens and data through CBridge\n/// @notice Used to differentiate between contract instances for mutable and immutable diamond as these cannot be shared\n/// @custom:version 2.0.0\nabstract contract CelerIMFacetBase is\n ILiFi,\n ReentrancyGuard,\n SwapperV2,\n Validatable\n{\n /// Storage ///\n\n /// @dev The contract address of the cBridge Message Bus\n IMessageBus private immutable cBridgeMessageBus;\n\n /// @dev The contract address of the RelayerCelerIM\n RelayerCelerIM public immutable relayer;\n\n /// @dev The contract address of the Celer Flow USDC\n address private immutable cfUSDC;\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _messageBus The contract address of the cBridge Message Bus\n /// @param _relayerOwner The address that will become the owner of the RelayerCelerIM contract\n /// @param _diamondAddress The address of the diamond contract that will be connected with the RelayerCelerIM\n /// @param _cfUSDC The contract address of the Celer Flow USDC\n constructor(\n IMessageBus _messageBus,\n address _relayerOwner,\n address _diamondAddress,\n address _cfUSDC\n ) {\n // deploy RelayerCelerIM\n relayer = new RelayerCelerIM(\n address(_messageBus),\n _relayerOwner,\n _diamondAddress\n );\n\n // store arguments in variables\n cBridgeMessageBus = _messageBus;\n cfUSDC = _cfUSDC;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via CBridge\n /// @param _bridgeData The core information needed for bridging\n /// @param _celerIMData Data specific to CelerIM\n function startBridgeTokensViaCelerIM(\n ILiFi.BridgeData memory _bridgeData,\n CelerIM.CelerIMData calldata _celerIMData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n validateDestinationCallFlag(_bridgeData, _celerIMData);\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // Transfer ERC20 tokens directly to relayer\n IERC20 asset = _getRightAsset(_bridgeData.sendingAssetId);\n\n // Deposit ERC20 token\n uint256 prevBalance = asset.balanceOf(address(relayer));\n SafeERC20.safeTransferFrom(\n asset,\n msg.sender,\n address(relayer),\n _bridgeData.minAmount\n );\n\n if (\n asset.balanceOf(address(relayer)) - prevBalance !=\n _bridgeData.minAmount\n ) {\n revert InvalidAmount();\n }\n }\n\n _startBridge(_bridgeData, _celerIMData);\n }\n\n /// @notice Performs a swap before bridging via CBridge\n /// @param _bridgeData The core information needed for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _celerIMData Data specific to CelerIM\n function swapAndStartBridgeTokensViaCelerIM(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n CelerIM.CelerIMData calldata _celerIMData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n validateDestinationCallFlag(_bridgeData, _celerIMData);\n\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n _celerIMData.messageBusFee\n );\n\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // Transfer ERC20 tokens directly to relayer\n IERC20 asset = _getRightAsset(_bridgeData.sendingAssetId);\n\n // Deposit ERC20 token\n uint256 prevBalance = asset.balanceOf(address(relayer));\n SafeERC20.safeTransfer(\n asset,\n address(relayer),\n _bridgeData.minAmount\n );\n\n if (\n asset.balanceOf(address(relayer)) - prevBalance !=\n _bridgeData.minAmount\n ) {\n revert InvalidAmount();\n }\n }\n\n _startBridge(_bridgeData, _celerIMData);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via CBridge\n /// @param _bridgeData The core information needed for bridging\n /// @param _celerIMData Data specific to CBridge\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n CelerIM.CelerIMData calldata _celerIMData\n ) private {\n // Assuming messageBusFee is pre-calculated off-chain and available in _celerIMData\n // Determine correct native asset amount to be forwarded (if so) and send funds to relayer\n uint256 msgValue = LibAsset.isNativeAsset(_bridgeData.sendingAssetId)\n ? _bridgeData.minAmount\n : 0;\n\n // Check if transaction contains a destination call\n if (!_bridgeData.hasDestinationCall) {\n // Case 'no': Simple bridge transfer - Send to receiver\n relayer.sendTokenTransfer{ value: msgValue }(\n _bridgeData,\n _celerIMData\n );\n } else {\n // Case 'yes': Bridge + Destination call - Send to relayer\n\n // save address of original recipient\n address receiver = _bridgeData.receiver;\n\n // Set relayer as a receiver\n _bridgeData.receiver = address(relayer);\n\n // send token transfer\n (bytes32 transferId, address bridgeAddress) = relayer\n .sendTokenTransfer{ value: msgValue }(\n _bridgeData,\n _celerIMData\n );\n\n // Call message bus via relayer incl messageBusFee\n relayer.forwardSendMessageWithTransfer{\n value: _celerIMData.messageBusFee\n }(\n _bridgeData.receiver,\n uint64(_bridgeData.destinationChainId),\n bridgeAddress,\n transferId,\n _celerIMData.callData\n );\n\n // Reset receiver of bridge data for event emission\n _bridgeData.receiver = receiver;\n }\n\n // emit LiFi event\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @dev Get right asset to transfer to relayer.\n /// @param _sendingAssetId The address of asset to bridge.\n /// @return _asset The address of asset to transfer to relayer.\n function _getRightAsset(\n address _sendingAssetId\n ) private returns (IERC20 _asset) {\n if (_sendingAssetId == cfUSDC) {\n // special case for cfUSDC token\n _asset = IERC20(CelerToken(_sendingAssetId).canonical());\n } else {\n // any other ERC20 token\n _asset = IERC20(_sendingAssetId);\n }\n }\n\n function validateDestinationCallFlag(\n ILiFi.BridgeData memory _bridgeData,\n CelerIM.CelerIMData calldata _celerIMData\n ) private pure {\n if (\n (_celerIMData.callData.length > 0) !=\n _bridgeData.hasDestinationCall\n ) {\n revert InformationMismatch();\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "lib/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\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 ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "lib/sgn-v2-contracts/contracts/message/libraries/MessageSenderLib.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"../../interfaces/IBridge.sol\";\nimport \"../../interfaces/IOriginalTokenVault.sol\";\nimport \"../../interfaces/IOriginalTokenVaultV2.sol\";\nimport \"../../interfaces/IPeggedTokenBridge.sol\";\nimport \"../../interfaces/IPeggedTokenBridgeV2.sol\";\nimport \"../interfaces/IMessageBus.sol\";\nimport \"./MsgDataTypes.sol\";\n\nlibrary MessageSenderLib {\n using SafeERC20 for IERC20;\n\n // ============== Internal library functions called by apps ==============\n\n /**\n * @notice Sends a message to an app on another chain via MessageBus without an associated transfer.\n * @param _receiver The address of the destination app contract.\n * @param _dstChainId The destination chain ID.\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\n * @param _messageBus The address of the MessageBus on this chain.\n * @param _fee The fee amount to pay to MessageBus.\n */\n function sendMessage(\n address _receiver,\n uint64 _dstChainId,\n bytes memory _message,\n address _messageBus,\n uint256 _fee\n ) internal {\n IMessageBus(_messageBus).sendMessage{value: _fee}(_receiver, _dstChainId, _message);\n }\n\n // Send message to non-evm chain with bytes for receiver address,\n // otherwise same as above.\n function sendMessage(\n bytes calldata _receiver,\n uint64 _dstChainId,\n bytes memory _message,\n address _messageBus,\n uint256 _fee\n ) internal {\n IMessageBus(_messageBus).sendMessage{value: _fee}(_receiver, _dstChainId, _message);\n }\n\n /**\n * @notice Sends a message to an app on another chain via MessageBus with an associated transfer.\n * @param _receiver The address of the destination app contract.\n * @param _token The address of the token to be sent.\n * @param _amount The amount of tokens to be sent.\n * @param _dstChainId The destination chain ID.\n * @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\n * @param _maxSlippage The max slippage accepted, given as percentage in point (pip). Eg. 5000 means 0.5%.\n * Must be greater than minimalMaxSlippage. Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount or the\n * transfer can be refunded. Only applicable to the {MsgDataTypes.BridgeSendType.Liquidity}.\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\n * @param _bridgeSendType One of the {MsgDataTypes.BridgeSendType} enum.\n * @param _messageBus The address of the MessageBus on this chain.\n * @param _fee The fee amount to pay to MessageBus.\n * @return The transfer ID.\n */\n function sendMessageWithTransfer(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce,\n uint32 _maxSlippage,\n bytes memory _message,\n MsgDataTypes.BridgeSendType _bridgeSendType,\n address _messageBus,\n uint256 _fee\n ) internal returns (bytes32) {\n (bytes32 transferId, address bridge) = sendTokenTransfer(\n _receiver,\n _token,\n _amount,\n _dstChainId,\n _nonce,\n _maxSlippage,\n _bridgeSendType,\n _messageBus\n );\n if (_message.length > 0) {\n IMessageBus(_messageBus).sendMessageWithTransfer{value: _fee}(\n _receiver,\n _dstChainId,\n bridge,\n transferId,\n _message\n );\n }\n return transferId;\n }\n\n /**\n * @notice Sends a token transfer via a bridge.\n * @param _receiver The address of the destination app contract.\n * @param _token The address of the token to be sent.\n * @param _amount The amount of tokens to be sent.\n * @param _dstChainId The destination chain ID.\n * @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\n * @param _maxSlippage The max slippage accepted, given as percentage in point (pip). Eg. 5000 means 0.5%.\n * Must be greater than minimalMaxSlippage. Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount or the\n * transfer can be refunded.\n * @param _bridgeSendType One of the {MsgDataTypes.BridgeSendType} enum.\n */\n function sendTokenTransfer(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce,\n uint32 _maxSlippage,\n MsgDataTypes.BridgeSendType _bridgeSendType,\n address _messageBus\n ) internal returns (bytes32 transferId, address bridge) {\n if (_bridgeSendType == MsgDataTypes.BridgeSendType.Liquidity) {\n bridge = IMessageBus(_messageBus).liquidityBridge();\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\n IBridge(bridge).send(_receiver, _token, _amount, _dstChainId, _nonce, _maxSlippage);\n transferId = computeLiqBridgeTransferId(_receiver, _token, _amount, _dstChainId, _nonce);\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegDeposit) {\n bridge = IMessageBus(_messageBus).pegVault();\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\n IOriginalTokenVault(bridge).deposit(_token, _amount, _dstChainId, _receiver, _nonce);\n transferId = computePegV1DepositId(_receiver, _token, _amount, _dstChainId, _nonce);\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegBurn) {\n bridge = IMessageBus(_messageBus).pegBridge();\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\n IPeggedTokenBridge(bridge).burn(_token, _amount, _receiver, _nonce);\n // handle cases where certain tokens do not spend allowance for role-based burn\n IERC20(_token).safeApprove(bridge, 0);\n transferId = computePegV1BurnId(_receiver, _token, _amount, _nonce);\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2Deposit) {\n bridge = IMessageBus(_messageBus).pegVaultV2();\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\n transferId = IOriginalTokenVaultV2(bridge).deposit(_token, _amount, _dstChainId, _receiver, _nonce);\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2Burn) {\n bridge = IMessageBus(_messageBus).pegBridgeV2();\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\n transferId = IPeggedTokenBridgeV2(bridge).burn(_token, _amount, _dstChainId, _receiver, _nonce);\n // handle cases where certain tokens do not spend allowance for role-based burn\n IERC20(_token).safeApprove(bridge, 0);\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2BurnFrom) {\n bridge = IMessageBus(_messageBus).pegBridgeV2();\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\n transferId = IPeggedTokenBridgeV2(bridge).burnFrom(_token, _amount, _dstChainId, _receiver, _nonce);\n // handle cases where certain tokens do not spend allowance for role-based burn\n IERC20(_token).safeApprove(bridge, 0);\n } else {\n revert(\"bridge type not supported\");\n }\n }\n\n function computeLiqBridgeTransferId(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce\n ) internal view returns (bytes32) {\n return\n keccak256(\n abi.encodePacked(address(this), _receiver, _token, _amount, _dstChainId, _nonce, uint64(block.chainid))\n );\n }\n\n function computePegV1DepositId(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce\n ) internal view returns (bytes32) {\n return\n keccak256(\n abi.encodePacked(address(this), _token, _amount, _dstChainId, _receiver, _nonce, uint64(block.chainid))\n );\n }\n\n function computePegV1BurnId(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _nonce\n ) internal view returns (bytes32) {\n return keccak256(abi.encodePacked(address(this), _token, _amount, _receiver, _nonce, uint64(block.chainid)));\n }\n}\n" + }, + "src/Periphery/RelayerCelerIM.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IERC20, SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { ContractCallNotAllowed, ExternalCallFailed, InvalidConfig, UnAuthorized, WithdrawFailed } from \"../Errors/GenericErrors.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { PeripheryRegistryFacet } from \"../Facets/PeripheryRegistryFacet.sol\";\nimport { IExecutor } from \"../Interfaces/IExecutor.sol\";\nimport { TransferrableOwnership } from \"../Helpers/TransferrableOwnership.sol\";\nimport { IMessageReceiverApp } from \"celer-network/contracts/message/interfaces/IMessageReceiverApp.sol\";\nimport { CelerIM } from \"lifi/Helpers/CelerIMFacetBase.sol\";\nimport { MessageSenderLib, MsgDataTypes, IMessageBus, IOriginalTokenVault, IPeggedTokenBridge, IOriginalTokenVaultV2, IPeggedTokenBridgeV2 } from \"celer-network/contracts/message/libraries/MessageSenderLib.sol\";\nimport { IBridge as ICBridge } from \"celer-network/contracts/interfaces/IBridge.sol\";\n\n/// @title RelayerCelerIM\n/// @author LI.FI (https://li.fi)\n/// @notice Relayer contract for CelerIM that forwards calls and handles refunds on src side and acts receiver on dest\n/// @custom:version 2.0.0\ncontract RelayerCelerIM is ILiFi, TransferrableOwnership {\n using SafeERC20 for IERC20;\n\n /// Storage ///\n\n IMessageBus public cBridgeMessageBus;\n address public diamondAddress;\n\n /// Events ///\n\n event LogWithdraw(\n address indexed _assetAddress,\n address indexed _to,\n uint256 amount\n );\n\n /// Modifiers ///\n\n modifier onlyCBridgeMessageBus() {\n if (msg.sender != address(cBridgeMessageBus)) revert UnAuthorized();\n _;\n }\n modifier onlyDiamond() {\n if (msg.sender != diamondAddress) revert UnAuthorized();\n _;\n }\n\n /// Constructor\n\n constructor(\n address _cBridgeMessageBusAddress,\n address _owner,\n address _diamondAddress\n ) TransferrableOwnership(_owner) {\n owner = _owner;\n cBridgeMessageBus = IMessageBus(_cBridgeMessageBusAddress);\n diamondAddress = _diamondAddress;\n }\n\n /// External Methods ///\n\n /**\n * @notice Called by MessageBus to execute a message with an associated token transfer.\n * The Receiver is guaranteed to have received the right amount of tokens before this function is called.\n * @param * (unused) The address of the source app contract\n * @param _token The address of the token that comes out of the bridge\n * @param _amount The amount of tokens received at this contract through the cross-chain bridge.\n * @param * (unused) The source chain ID where the transfer is originated from\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param * (unused) Address who called the MessageBus execution function\n */\n function executeMessageWithTransfer(\n address,\n address _token,\n uint256 _amount,\n uint64,\n bytes calldata _message,\n address\n )\n external\n payable\n onlyCBridgeMessageBus\n returns (IMessageReceiverApp.ExecutionStatus)\n {\n // decode message\n (\n bytes32 transactionId,\n LibSwap.SwapData[] memory swapData,\n address receiver,\n address refundAddress\n ) = abi.decode(\n _message,\n (bytes32, LibSwap.SwapData[], address, address)\n );\n\n _swapAndCompleteBridgeTokens(\n transactionId,\n swapData,\n _token,\n payable(receiver),\n _amount,\n refundAddress\n );\n\n return IMessageReceiverApp.ExecutionStatus.Success;\n }\n\n /**\n * @notice Called by MessageBus to process refund of the original transfer from this contract.\n * The contract is guaranteed to have received the refund before this function is called.\n * @param _token The token address of the original transfer\n * @param _amount The amount of the original transfer\n * @param _message The same message associated with the original transfer\n * @param * (unused) Address who called the MessageBus execution function\n */\n function executeMessageWithTransferRefund(\n address _token,\n uint256 _amount,\n bytes calldata _message,\n address\n )\n external\n payable\n onlyCBridgeMessageBus\n returns (IMessageReceiverApp.ExecutionStatus)\n {\n (bytes32 transactionId, , , address refundAddress) = abi.decode(\n _message,\n (bytes32, LibSwap.SwapData[], address, address)\n );\n\n // return funds to cBridgeData.refundAddress\n LibAsset.transferAsset(_token, payable(refundAddress), _amount);\n\n emit LiFiTransferRecovered(\n transactionId,\n _token,\n refundAddress,\n _amount,\n block.timestamp\n );\n\n return IMessageReceiverApp.ExecutionStatus.Success;\n }\n\n /**\n * @notice Forwards a call to transfer tokens to cBridge (sent via this contract to ensure that potential refunds are sent here)\n * @param _bridgeData the core information needed for bridging\n * @param _celerIMData data specific to CelerIM\n */\n // solhint-disable-next-line code-complexity\n function sendTokenTransfer(\n ILiFi.BridgeData memory _bridgeData,\n CelerIM.CelerIMData calldata _celerIMData\n )\n external\n payable\n onlyDiamond\n returns (bytes32 transferId, address bridgeAddress)\n {\n // approve to and call correct bridge depending on BridgeSendType\n // @dev copied and slightly adapted from Celer MessageSenderLib\n if (_celerIMData.bridgeType == MsgDataTypes.BridgeSendType.Liquidity) {\n bridgeAddress = cBridgeMessageBus.liquidityBridge();\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // case: native asset bridging\n ICBridge(bridgeAddress).sendNative{\n value: _bridgeData.minAmount\n }(\n _bridgeData.receiver,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _celerIMData.nonce,\n _celerIMData.maxSlippage\n );\n } else {\n // case: ERC20 asset bridging\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n bridgeAddress,\n _bridgeData.minAmount\n );\n // solhint-disable-next-line check-send-result\n ICBridge(bridgeAddress).send(\n _bridgeData.receiver,\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _celerIMData.nonce,\n _celerIMData.maxSlippage\n );\n }\n transferId = MessageSenderLib.computeLiqBridgeTransferId(\n _bridgeData.receiver,\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _celerIMData.nonce\n );\n } else if (\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegDeposit\n ) {\n bridgeAddress = cBridgeMessageBus.pegVault();\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n bridgeAddress,\n _bridgeData.minAmount\n );\n IOriginalTokenVault(bridgeAddress).deposit(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _bridgeData.receiver,\n _celerIMData.nonce\n );\n transferId = MessageSenderLib.computePegV1DepositId(\n _bridgeData.receiver,\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _celerIMData.nonce\n );\n } else if (\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegBurn\n ) {\n bridgeAddress = cBridgeMessageBus.pegBridge();\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n bridgeAddress,\n _bridgeData.minAmount\n );\n IPeggedTokenBridge(bridgeAddress).burn(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n _bridgeData.receiver,\n _celerIMData.nonce\n );\n transferId = MessageSenderLib.computePegV1BurnId(\n _bridgeData.receiver,\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n _celerIMData.nonce\n );\n } else if (\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegV2Deposit\n ) {\n bridgeAddress = cBridgeMessageBus.pegVaultV2();\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // case: native asset bridging\n transferId = IOriginalTokenVaultV2(bridgeAddress)\n .depositNative{ value: _bridgeData.minAmount }(\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _bridgeData.receiver,\n _celerIMData.nonce\n );\n } else {\n // case: ERC20 bridging\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n bridgeAddress,\n _bridgeData.minAmount\n );\n transferId = IOriginalTokenVaultV2(bridgeAddress).deposit(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _bridgeData.receiver,\n _celerIMData.nonce\n );\n }\n } else if (\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegV2Burn\n ) {\n bridgeAddress = cBridgeMessageBus.pegBridgeV2();\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n bridgeAddress,\n _bridgeData.minAmount\n );\n transferId = IPeggedTokenBridgeV2(bridgeAddress).burn(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _bridgeData.receiver,\n _celerIMData.nonce\n );\n } else if (\n _celerIMData.bridgeType ==\n MsgDataTypes.BridgeSendType.PegV2BurnFrom\n ) {\n bridgeAddress = cBridgeMessageBus.pegBridgeV2();\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n bridgeAddress,\n _bridgeData.minAmount\n );\n transferId = IPeggedTokenBridgeV2(bridgeAddress).burnFrom(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _bridgeData.receiver,\n _celerIMData.nonce\n );\n } else {\n revert InvalidConfig();\n }\n }\n\n /**\n * @notice Forwards a call to the CBridge Messagebus\n * @param _receiver The address of the destination app contract.\n * @param _dstChainId The destination chain ID.\n * @param _srcBridge The bridge contract to send the transfer with.\n * @param _srcTransferId The transfer ID.\n * @param _dstChainId The destination chain ID.\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\n */\n function forwardSendMessageWithTransfer(\n address _receiver,\n uint256 _dstChainId,\n address _srcBridge,\n bytes32 _srcTransferId,\n bytes calldata _message\n ) external payable onlyDiamond {\n cBridgeMessageBus.sendMessageWithTransfer{ value: msg.value }(\n _receiver,\n _dstChainId,\n _srcBridge,\n _srcTransferId,\n _message\n );\n }\n\n // ------------------------------------------------------------------------------------------------\n\n /// Private Methods ///\n\n /// @notice Performs a swap before completing a cross-chain transaction\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swapData array of data needed for swaps\n /// @param assetId token received from the other chain\n /// @param receiver address that will receive tokens in the end\n /// @param amount amount of token\n function _swapAndCompleteBridgeTokens(\n bytes32 _transactionId,\n LibSwap.SwapData[] memory _swapData,\n address assetId,\n address payable receiver,\n uint256 amount,\n address refundAddress\n ) private {\n bool success;\n IExecutor executor = IExecutor(\n PeripheryRegistryFacet(diamondAddress).getPeripheryContract(\n \"Executor\"\n )\n );\n if (LibAsset.isNativeAsset(assetId)) {\n try\n executor.swapAndCompleteBridgeTokens{ value: amount }(\n _transactionId,\n _swapData,\n assetId,\n receiver\n )\n {\n success = true;\n } catch {\n // solhint-disable-next-line avoid-low-level-calls\n (bool fundsSent, ) = refundAddress.call{ value: amount }(\"\");\n if (!fundsSent) {\n revert ExternalCallFailed();\n }\n }\n } else {\n IERC20 token = IERC20(assetId);\n token.safeApprove(address(executor), 0);\n token.safeIncreaseAllowance(address(executor), amount);\n\n try\n executor.swapAndCompleteBridgeTokens(\n _transactionId,\n _swapData,\n assetId,\n receiver\n )\n {\n success = true;\n } catch {\n token.safeTransfer(refundAddress, amount);\n }\n token.safeApprove(address(executor), 0);\n }\n\n if (!success) {\n emit LiFiTransferRecovered(\n _transactionId,\n assetId,\n refundAddress,\n amount,\n block.timestamp\n );\n }\n }\n\n /// @notice Sends remaining token to given receiver address (for refund cases)\n /// @param assetId Address of the token to be withdrawn\n /// @param receiver Address that will receive tokens\n /// @param amount Amount of tokens to be withdrawn\n function withdraw(\n address assetId,\n address payable receiver,\n uint256 amount\n ) external onlyOwner {\n if (LibAsset.isNativeAsset(assetId)) {\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = receiver.call{ value: amount }(\"\");\n if (!success) {\n revert WithdrawFailed();\n }\n } else {\n IERC20(assetId).safeTransfer(receiver, amount);\n }\n emit LogWithdraw(assetId, receiver, amount);\n }\n\n /// @notice Triggers a cBridge refund with calldata produced by cBridge API\n /// @param _callTo The address to execute the calldata on\n /// @param _callData The data to execute\n /// @param _assetAddress Asset to be withdrawn\n /// @param _to Address to withdraw to\n /// @param _amount Amount of asset to withdraw\n function triggerRefund(\n address payable _callTo,\n bytes calldata _callData,\n address _assetAddress,\n address _to,\n uint256 _amount\n ) external onlyOwner {\n bool success;\n\n // make sure that callTo address is either of the cBridge addresses\n if (\n cBridgeMessageBus.liquidityBridge() != _callTo &&\n cBridgeMessageBus.pegBridge() != _callTo &&\n cBridgeMessageBus.pegBridgeV2() != _callTo &&\n cBridgeMessageBus.pegVault() != _callTo &&\n cBridgeMessageBus.pegVaultV2() != _callTo\n ) {\n revert ContractCallNotAllowed();\n }\n\n // call contract\n // solhint-disable-next-line avoid-low-level-calls\n (success, ) = _callTo.call(_callData);\n\n // forward funds to _to address and emit event, if cBridge refund successful\n if (success) {\n address sendTo = (LibUtil.isZeroAddress(_to)) ? msg.sender : _to;\n LibAsset.transferAsset(_assetAddress, payable(sendTo), _amount);\n emit LogWithdraw(_assetAddress, sendTo, _amount);\n } else {\n revert WithdrawFailed();\n }\n }\n\n // required in order to receive native tokens from cBridge facet\n // solhint-disable-next-line no-empty-blocks\n receive() external payable {}\n}\n" + }, + "lib/openzeppelin-contracts/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" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "lib/sgn-v2-contracts/contracts/interfaces/IBridge.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\ninterface IBridge {\n function send(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce,\n uint32 _maxSlippage\n ) external;\n\n function sendNative(\n address _receiver,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce,\n uint32 _maxSlippage\n ) external payable;\n\n function relay(\n bytes calldata _relayRequest,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external;\n\n function transfers(bytes32 transferId) external view returns (bool);\n\n function withdraws(bytes32 withdrawId) external view returns (bool);\n\n function withdraw(\n bytes calldata _wdmsg,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external;\n\n /**\n * @notice Verifies that a message is signed by a quorum among the signers.\n * @param _msg signed message\n * @param _sigs list of signatures sorted by signer addresses in ascending order\n * @param _signers sorted list of current signers\n * @param _powers powers of current signers\n */\n function verifySigs(\n bytes memory _msg,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external view;\n}\n" + }, + "lib/sgn-v2-contracts/contracts/interfaces/IOriginalTokenVault.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\ninterface IOriginalTokenVault {\n /**\n * @notice Lock original tokens to trigger mint at a remote chain's PeggedTokenBridge\n * @param _token local token address\n * @param _amount locked token amount\n * @param _mintChainId destination chainId to mint tokens\n * @param _mintAccount destination account to receive minted tokens\n * @param _nonce user input to guarantee unique depositId\n */\n function deposit(\n address _token,\n uint256 _amount,\n uint64 _mintChainId,\n address _mintAccount,\n uint64 _nonce\n ) external;\n\n /**\n * @notice Lock native token as original token to trigger mint at a remote chain's PeggedTokenBridge\n * @param _amount locked token amount\n * @param _mintChainId destination chainId to mint tokens\n * @param _mintAccount destination account to receive minted tokens\n * @param _nonce user input to guarantee unique depositId\n */\n function depositNative(\n uint256 _amount,\n uint64 _mintChainId,\n address _mintAccount,\n uint64 _nonce\n ) external payable;\n\n /**\n * @notice Withdraw locked original tokens triggered by a burn at a remote chain's PeggedTokenBridge.\n * @param _request The serialized Withdraw protobuf.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the bridge's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function withdraw(\n bytes calldata _request,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external;\n\n function records(bytes32 recordId) external view returns (bool);\n}\n" + }, + "lib/sgn-v2-contracts/contracts/interfaces/IOriginalTokenVaultV2.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\ninterface IOriginalTokenVaultV2 {\n /**\n * @notice Lock original tokens to trigger mint at a remote chain's PeggedTokenBridge\n * @param _token local token address\n * @param _amount locked token amount\n * @param _mintChainId destination chainId to mint tokens\n * @param _mintAccount destination account to receive minted tokens\n * @param _nonce user input to guarantee unique depositId\n */\n function deposit(\n address _token,\n uint256 _amount,\n uint64 _mintChainId,\n address _mintAccount,\n uint64 _nonce\n ) external returns (bytes32);\n\n /**\n * @notice Lock native token as original token to trigger mint at a remote chain's PeggedTokenBridge\n * @param _amount locked token amount\n * @param _mintChainId destination chainId to mint tokens\n * @param _mintAccount destination account to receive minted tokens\n * @param _nonce user input to guarantee unique depositId\n */\n function depositNative(\n uint256 _amount,\n uint64 _mintChainId,\n address _mintAccount,\n uint64 _nonce\n ) external payable returns (bytes32);\n\n /**\n * @notice Withdraw locked original tokens triggered by a burn at a remote chain's PeggedTokenBridge.\n * @param _request The serialized Withdraw protobuf.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the bridge's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function withdraw(\n bytes calldata _request,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external returns (bytes32);\n\n function records(bytes32 recordId) external view returns (bool);\n}\n" + }, + "lib/sgn-v2-contracts/contracts/interfaces/IPeggedTokenBridge.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\ninterface IPeggedTokenBridge {\n /**\n * @notice Burn tokens to trigger withdrawal at a remote chain's OriginalTokenVault\n * @param _token local token address\n * @param _amount locked token amount\n * @param _withdrawAccount account who withdraw original tokens on the remote chain\n * @param _nonce user input to guarantee unique depositId\n */\n function burn(\n address _token,\n uint256 _amount,\n address _withdrawAccount,\n uint64 _nonce\n ) external;\n\n /**\n * @notice Mint tokens triggered by deposit at a remote chain's OriginalTokenVault.\n * @param _request The serialized Mint protobuf.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the sigsVerifier's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function mint(\n bytes calldata _request,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external;\n\n function records(bytes32 recordId) external view returns (bool);\n}\n" + }, + "lib/sgn-v2-contracts/contracts/interfaces/IPeggedTokenBridgeV2.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\ninterface IPeggedTokenBridgeV2 {\n /**\n * @notice Burn pegged tokens to trigger a cross-chain withdrawal of the original tokens at a remote chain's\n * OriginalTokenVault, or mint at another remote chain\n * @param _token The pegged token address.\n * @param _amount The amount to burn.\n * @param _toChainId If zero, withdraw from original vault; otherwise, the remote chain to mint tokens.\n * @param _toAccount The account to receive tokens on the remote chain\n * @param _nonce A number to guarantee unique depositId. Can be timestamp in practice.\n */\n function burn(\n address _token,\n uint256 _amount,\n uint64 _toChainId,\n address _toAccount,\n uint64 _nonce\n ) external returns (bytes32);\n\n // same with `burn` above, use openzeppelin ERC20Burnable interface\n function burnFrom(\n address _token,\n uint256 _amount,\n uint64 _toChainId,\n address _toAccount,\n uint64 _nonce\n ) external returns (bytes32);\n\n /**\n * @notice Mint tokens triggered by deposit at a remote chain's OriginalTokenVault.\n * @param _request The serialized Mint protobuf.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the sigsVerifier's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function mint(\n bytes calldata _request,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external returns (bytes32);\n\n function records(bytes32 recordId) external view returns (bool);\n}\n" + }, + "lib/sgn-v2-contracts/contracts/message/interfaces/IMessageBus.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\nimport \"../libraries/MsgDataTypes.sol\";\n\ninterface IMessageBus {\n /**\n * @notice Send a message to a contract on another chain.\n * Sender needs to make sure the uniqueness of the message Id, which is computed as\n * hash(type.MessageOnly, sender, receiver, srcChainId, srcTxHash, dstChainId, message).\n * If messages with the same Id are sent, only one of them will succeed at dst chain..\n * A fee is charged in the native gas token.\n * @param _receiver The address of the destination app contract.\n * @param _dstChainId The destination chain ID.\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\n */\n function sendMessage(\n address _receiver,\n uint256 _dstChainId,\n bytes calldata _message\n ) external payable;\n\n // same as above, except that receiver is an non-evm chain address,\n function sendMessage(\n bytes calldata _receiver,\n uint256 _dstChainId,\n bytes calldata _message\n ) external payable;\n\n /**\n * @notice Send a message associated with a token transfer to a contract on another chain.\n * If messages with the same srcTransferId are sent, only one of them will succeed at dst chain..\n * A fee is charged in the native token.\n * @param _receiver The address of the destination app contract.\n * @param _dstChainId The destination chain ID.\n * @param _srcBridge The bridge contract to send the transfer with.\n * @param _srcTransferId The transfer ID.\n * @param _dstChainId The destination chain ID.\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\n */\n function sendMessageWithTransfer(\n address _receiver,\n uint256 _dstChainId,\n address _srcBridge,\n bytes32 _srcTransferId,\n bytes calldata _message\n ) external payable;\n\n /**\n * @notice Execute a message not associated with a transfer.\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the sigsVerifier's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function executeMessage(\n bytes calldata _message,\n MsgDataTypes.RouteInfo calldata _route,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external payable;\n\n /**\n * @notice Execute a message with a successful transfer.\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param _transfer The transfer info.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the sigsVerifier's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function executeMessageWithTransfer(\n bytes calldata _message,\n MsgDataTypes.TransferInfo calldata _transfer,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external payable;\n\n /**\n * @notice Execute a message with a refunded transfer.\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param _transfer The transfer info.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the sigsVerifier's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function executeMessageWithTransferRefund(\n bytes calldata _message, // the same message associated with the original transfer\n MsgDataTypes.TransferInfo calldata _transfer,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external payable;\n\n /**\n * @notice Withdraws message fee in the form of native gas token.\n * @param _account The address receiving the fee.\n * @param _cumulativeFee The cumulative fee credited to the account. Tracked by SGN.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A withdrawal must be\n * signed-off by +2/3 of the sigsVerifier's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function withdrawFee(\n address _account,\n uint256 _cumulativeFee,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external;\n\n /**\n * @notice Calculates the required fee for the message.\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\n @ @return The required fee.\n */\n function calcFee(bytes calldata _message) external view returns (uint256);\n\n function liquidityBridge() external view returns (address);\n\n function pegBridge() external view returns (address);\n\n function pegBridgeV2() external view returns (address);\n\n function pegVault() external view returns (address);\n\n function pegVaultV2() external view returns (address);\n}\n" + }, + "lib/sgn-v2-contracts/contracts/message/libraries/MsgDataTypes.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\nlibrary MsgDataTypes {\n string constant ABORT_PREFIX = \"MSG::ABORT:\";\n\n // bridge operation type at the sender side (src chain)\n enum BridgeSendType {\n Null,\n Liquidity,\n PegDeposit,\n PegBurn,\n PegV2Deposit,\n PegV2Burn,\n PegV2BurnFrom\n }\n\n // bridge operation type at the receiver side (dst chain)\n enum TransferType {\n Null,\n LqRelay, // relay through liquidity bridge\n LqWithdraw, // withdraw from liquidity bridge\n PegMint, // mint through pegged token bridge\n PegWithdraw, // withdraw from original token vault\n PegV2Mint, // mint through pegged token bridge v2\n PegV2Withdraw // withdraw from original token vault v2\n }\n\n enum MsgType {\n MessageWithTransfer,\n MessageOnly\n }\n\n enum TxStatus {\n Null,\n Success,\n Fail,\n Fallback,\n Pending // transient state within a transaction\n }\n\n struct TransferInfo {\n TransferType t;\n address sender;\n address receiver;\n address token;\n uint256 amount;\n uint64 wdseq; // only needed for LqWithdraw (refund)\n uint64 srcChainId;\n bytes32 refId;\n bytes32 srcTxHash; // src chain msg tx hash\n }\n\n struct RouteInfo {\n address sender;\n address receiver;\n uint64 srcChainId;\n bytes32 srcTxHash; // src chain msg tx hash\n }\n\n // used for msg from non-evm chains with longer-bytes address\n struct RouteInfo2 {\n bytes sender;\n address receiver;\n uint64 srcChainId;\n bytes32 srcTxHash;\n }\n\n // combination of RouteInfo and RouteInfo2 for easier processing\n struct Route {\n address sender; // from RouteInfo\n bytes senderBytes; // from RouteInfo2\n address receiver;\n uint64 srcChainId;\n bytes32 srcTxHash;\n }\n\n struct MsgWithTransferExecutionParams {\n bytes message;\n TransferInfo transfer;\n bytes[] sigs;\n address[] signers;\n uint256[] powers;\n }\n\n struct BridgeTransferParams {\n bytes request;\n bytes[] sigs;\n address[] signers;\n uint256[] powers;\n }\n}\n" + }, + "src/Facets/PeripheryRegistryFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\n\n/// @title Periphery Registry Facet\n/// @author LI.FI (https://li.fi)\n/// @notice A simple registry to track LIFI periphery contracts\n/// @custom:version 1.0.0\ncontract PeripheryRegistryFacet {\n /// Storage ///\n\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.facets.periphery_registry\");\n\n /// Types ///\n\n struct Storage {\n mapping(string => address) contracts;\n }\n\n /// Events ///\n\n event PeripheryContractRegistered(string name, address contractAddress);\n\n /// External Methods ///\n\n /// @notice Registers a periphery contract address with a specified name\n /// @param _name the name to register the contract address under\n /// @param _contractAddress the address of the contract to register\n function registerPeripheryContract(\n string calldata _name,\n address _contractAddress\n ) external {\n LibDiamond.enforceIsContractOwner();\n Storage storage s = getStorage();\n s.contracts[_name] = _contractAddress;\n emit PeripheryContractRegistered(_name, _contractAddress);\n }\n\n /// @notice Returns the registered contract address by its name\n /// @param _name the registered name of the contract\n function getPeripheryContract(\n string calldata _name\n ) external view returns (address) {\n return getStorage().contracts[_name];\n }\n\n /// @dev fetch local storage\n function getStorage() private pure returns (Storage storage s) {\n bytes32 namespace = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n s.slot := namespace\n }\n }\n}\n" + }, + "src/Interfaces/IExecutor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\n/// @title Interface for Executor\n/// @author LI.FI (https://li.fi)\ninterface IExecutor {\n /// @notice Performs a swap before completing a cross-chain transaction\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swapData array of data needed for swaps\n /// @param transferredAssetId token received from the other chain\n /// @param receiver address that will receive tokens in the end\n function swapAndCompleteBridgeTokens(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swapData,\n address transferredAssetId,\n address payable receiver\n ) external payable;\n}\n" + }, + "src/Helpers/TransferrableOwnership.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IERC173 } from \"../Interfaces/IERC173.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\n\ncontract TransferrableOwnership is IERC173 {\n address public owner;\n address public pendingOwner;\n\n /// Errors ///\n error UnAuthorized();\n error NoNullOwner();\n error NewOwnerMustNotBeSelf();\n error NoPendingOwnershipTransfer();\n error NotPendingOwner();\n\n /// Events ///\n event OwnershipTransferRequested(\n address indexed _from,\n address indexed _to\n );\n\n constructor(address initialOwner) {\n owner = initialOwner;\n }\n\n modifier onlyOwner() {\n if (msg.sender != owner) revert UnAuthorized();\n _;\n }\n\n /// @notice Initiates transfer of ownership to a new address\n /// @param _newOwner the address to transfer ownership to\n function transferOwnership(address _newOwner) external onlyOwner {\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\n pendingOwner = _newOwner;\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\n }\n\n /// @notice Cancel transfer of ownership\n function cancelOwnershipTransfer() external onlyOwner {\n if (pendingOwner == LibAsset.NULL_ADDRESS)\n revert NoPendingOwnershipTransfer();\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\n function confirmOwnershipTransfer() external {\n address _pendingOwner = pendingOwner;\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n}\n" + }, + "lib/sgn-v2-contracts/contracts/message/interfaces/IMessageReceiverApp.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\ninterface IMessageReceiverApp {\n enum ExecutionStatus {\n Fail, // execution failed, finalized\n Success, // execution succeeded, finalized\n Retry // execution rejected, can retry later\n }\n\n /**\n * @notice Called by MessageBus to execute a message\n * @param _sender The address of the source app contract\n * @param _srcChainId The source chain ID where the transfer is originated from\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param _executor Address who called the MessageBus execution function\n */\n function executeMessage(\n address _sender,\n uint64 _srcChainId,\n bytes calldata _message,\n address _executor\n ) external payable returns (ExecutionStatus);\n\n // same as above, except that sender is an non-evm chain address,\n // otherwise same as above.\n function executeMessage(\n bytes calldata _sender,\n uint64 _srcChainId,\n bytes calldata _message,\n address _executor\n ) external payable returns (ExecutionStatus);\n\n /**\n * @notice Called by MessageBus to execute a message with an associated token transfer.\n * The contract is guaranteed to have received the right amount of tokens before this function is called.\n * @param _sender The address of the source app contract\n * @param _token The address of the token that comes out of the bridge\n * @param _amount The amount of tokens received at this contract through the cross-chain bridge.\n * @param _srcChainId The source chain ID where the transfer is originated from\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param _executor Address who called the MessageBus execution function\n */\n function executeMessageWithTransfer(\n address _sender,\n address _token,\n uint256 _amount,\n uint64 _srcChainId,\n bytes calldata _message,\n address _executor\n ) external payable returns (ExecutionStatus);\n\n /**\n * @notice Only called by MessageBus if\n * 1. executeMessageWithTransfer reverts, or\n * 2. executeMessageWithTransfer returns ExecutionStatus.Fail\n * The contract is guaranteed to have received the right amount of tokens before this function is called.\n * @param _sender The address of the source app contract\n * @param _token The address of the token that comes out of the bridge\n * @param _amount The amount of tokens received at this contract through the cross-chain bridge.\n * @param _srcChainId The source chain ID where the transfer is originated from\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param _executor Address who called the MessageBus execution function\n */\n function executeMessageWithTransferFallback(\n address _sender,\n address _token,\n uint256 _amount,\n uint64 _srcChainId,\n bytes calldata _message,\n address _executor\n ) external payable returns (ExecutionStatus);\n\n /**\n * @notice Called by MessageBus to process refund of the original transfer from this contract.\n * The contract is guaranteed to have received the refund before this function is called.\n * @param _token The token address of the original transfer\n * @param _amount The amount of the original transfer\n * @param _message The same message associated with the original transfer\n * @param _executor Address who called the MessageBus execution function\n */\n function executeMessageWithTransferRefund(\n address _token,\n uint256 _amount,\n bytes calldata _message,\n address _executor\n ) external payable returns (ExecutionStatus);\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Interfaces/IERC173.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\n/// @title ERC-173 Contract Ownership Standard\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\n/* is ERC165 */\ninterface IERC173 {\n /// @dev This emits when ownership of a contract changes.\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n /// @notice Get the address of the owner\n /// @return owner_ The address of the owner.\n function owner() external view returns (address owner_);\n\n /// @notice Set the address of the new owner of the contract\n /// @dev Set _newOwner to address(0) to renounce any ownership.\n /// @param _newOwner The address of the new owner of the contract\n function transferOwnership(address _newOwner) external;\n}\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +2.0.0 + Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... /StandardizedCallFacet +0x175e7799da0cd40e641352eab90d8e39e02a4ca9 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/StandardizedCallFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\n\\n/// @title Standardized Call Facet\\n/// @author LIFI https://li.finance ed@li.finance\\n/// @notice Allows calling different facet methods through a single standardized entrypoint\\n/// @custom:version 1.1.0\\ncontract StandardizedCallFacet {\\n /// External Methods ///\\n\\n /// @notice Make a standardized call to a facet\\n /// @param callData The calldata to forward to the facet\\n function standardizedCall(bytes memory callData) external payable {\\n execute(callData);\\n }\\n\\n /// @notice Make a standardized call to a facet\\n /// @param callData The calldata to forward to the facet\\n function standardizedSwapCall(bytes memory callData) external payable {\\n execute(callData);\\n }\\n\\n /// @notice Make a standardized call to a facet\\n /// @param callData The calldata to forward to the facet\\n function standardizedBridgeCall(bytes memory callData) external payable {\\n execute(callData);\\n }\\n\\n /// @notice Make a standardized call to a facet\\n /// @param callData The calldata to forward to the facet\\n function standardizedSwapAndBridgeCall(\\n bytes memory callData\\n ) external payable {\\n execute(callData);\\n }\\n\\n function execute(bytes memory callData) internal {\\n // Fetch the facetAddress from the dimaond's internal storage\\n // Cheaper than calling the external facetAddress(selector) method directly\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n address facetAddress = ds\\n .selectorToFacetAndPosition[bytes4(callData)]\\n .facetAddress;\\n\\n if (facetAddress == address(0)) {\\n revert LibDiamond.FunctionDoesNotExist();\\n }\\n\\n // Execute external function from facet using delegatecall and return any value.\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n // execute function call using the facet\\n let result := delegatecall(\\n gas(),\\n facetAddress,\\n add(callData, 0x20),\\n mload(callData),\\n 0,\\n 0\\n )\\n // get any return value\\n returndatacopy(0, 0, returndatasize())\\n // return any return value or error back to the caller\\n switch result\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[],\"name\":\"FunctionDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"name\":\"standardizedBridgeCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"name\":\"standardizedCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"name\":\"standardizedSwapAndBridgeCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"name\":\"standardizedSwapCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "StandardizedCallFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "0x637ac9addc9c38b3f52878e11620a9060dc71d8b", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/StandardizedCallFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\n\n/// @title Standardized Call Facet\n/// @author LIFI https://li.finance ed@li.finance\n/// @notice Allows calling different facet methods through a single standardized entrypoint\n/// @custom:version 1.1.0\ncontract StandardizedCallFacet {\n /// External Methods ///\n\n /// @notice Make a standardized call to a facet\n /// @param callData The calldata to forward to the facet\n function standardizedCall(bytes memory callData) external payable {\n execute(callData);\n }\n\n /// @notice Make a standardized call to a facet\n /// @param callData The calldata to forward to the facet\n function standardizedSwapCall(bytes memory callData) external payable {\n execute(callData);\n }\n\n /// @notice Make a standardized call to a facet\n /// @param callData The calldata to forward to the facet\n function standardizedBridgeCall(bytes memory callData) external payable {\n execute(callData);\n }\n\n /// @notice Make a standardized call to a facet\n /// @param callData The calldata to forward to the facet\n function standardizedSwapAndBridgeCall(\n bytes memory callData\n ) external payable {\n execute(callData);\n }\n\n function execute(bytes memory callData) internal {\n // Fetch the facetAddress from the dimaond's internal storage\n // Cheaper than calling the external facetAddress(selector) method directly\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n address facetAddress = ds\n .selectorToFacetAndPosition[bytes4(callData)]\n .facetAddress;\n\n if (facetAddress == address(0)) {\n revert LibDiamond.FunctionDoesNotExist();\n }\n\n // Execute external function from facet using delegatecall and return any value.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n // execute function call using the facet\n let result := delegatecall(\n gas(),\n facetAddress,\n add(callData, 0x20),\n mload(callData),\n 0,\n 0\n )\n // get any return value\n returndatacopy(0, 0, returndatasize())\n // return any return value or error back to the caller\n switch result\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +1.1.0 + Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... /CalldataVerificationFacet +0x7a5c119ec5ddbf9631cf40f6e5db28f31d4332a0 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/CalldataVerificationFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { AmarokFacet } from \\\"./AmarokFacet.sol\\\";\\nimport { StargateFacet } from \\\"./StargateFacet.sol\\\";\\nimport { CelerIMFacetBase, CelerIM } from \\\"lifi/Helpers/CelerIMFacetBase.sol\\\";\\nimport { StandardizedCallFacet } from \\\"lifi/Facets/StandardizedCallFacet.sol\\\";\\nimport { LibBytes } from \\\"../Libraries/LibBytes.sol\\\";\\n\\n/// @title Calldata Verification Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for verifying calldata\\n/// @custom:version 1.1.1\\ncontract CalldataVerificationFacet {\\n using LibBytes for bytes;\\n\\n /// @notice Extracts the bridge data from the calldata\\n /// @param data The calldata to extract the bridge data from\\n /// @return bridgeData The bridge data extracted from the calldata\\n function extractBridgeData(\\n bytes calldata data\\n ) external pure returns (ILiFi.BridgeData memory bridgeData) {\\n bridgeData = _extractBridgeData(data);\\n }\\n\\n /// @notice Extracts the swap data from the calldata\\n /// @param data The calldata to extract the swap data from\\n /// @return swapData The swap data extracted from the calldata\\n function extractSwapData(\\n bytes calldata data\\n ) external pure returns (LibSwap.SwapData[] memory swapData) {\\n swapData = _extractSwapData(data);\\n }\\n\\n /// @notice Extracts the bridge data and swap data from the calldata\\n /// @param data The calldata to extract the bridge data and swap data from\\n /// @return bridgeData The bridge data extracted from the calldata\\n /// @return swapData The swap data extracted from the calldata\\n function extractData(\\n bytes calldata data\\n )\\n external\\n pure\\n returns (\\n ILiFi.BridgeData memory bridgeData,\\n LibSwap.SwapData[] memory swapData\\n )\\n {\\n bridgeData = _extractBridgeData(data);\\n if (bridgeData.hasSourceSwaps) {\\n swapData = _extractSwapData(data);\\n }\\n }\\n\\n /// @notice Extracts the main parameters from the calldata\\n /// @param data The calldata to extract the main parameters from\\n /// @return bridge The bridge extracted from the calldata\\n /// @return sendingAssetId The sending asset id extracted from the calldata\\n /// @return receiver The receiver extracted from the calldata\\n /// @return amount The min amountfrom the calldata\\n /// @return destinationChainId The destination chain id extracted from the calldata\\n /// @return hasSourceSwaps Whether the calldata has source swaps\\n /// @return hasDestinationCall Whether the calldata has a destination call\\n function extractMainParameters(\\n bytes calldata data\\n )\\n public\\n pure\\n returns (\\n string memory bridge,\\n address sendingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 destinationChainId,\\n bool hasSourceSwaps,\\n bool hasDestinationCall\\n )\\n {\\n ILiFi.BridgeData memory bridgeData = _extractBridgeData(data);\\n\\n if (bridgeData.hasSourceSwaps) {\\n LibSwap.SwapData[] memory swapData = _extractSwapData(data);\\n sendingAssetId = swapData[0].sendingAssetId;\\n amount = swapData[0].fromAmount;\\n } else {\\n sendingAssetId = bridgeData.sendingAssetId;\\n amount = bridgeData.minAmount;\\n }\\n\\n return (\\n bridgeData.bridge,\\n sendingAssetId,\\n bridgeData.receiver,\\n amount,\\n bridgeData.destinationChainId,\\n bridgeData.hasSourceSwaps,\\n bridgeData.hasDestinationCall\\n );\\n }\\n\\n /// @notice Extracts the generic swap parameters from the calldata\\n /// @param data The calldata to extract the generic swap parameters from\\n /// @return sendingAssetId The sending asset id extracted from the calldata\\n /// @return amount The amount extracted from the calldata\\n /// @return receiver The receiver extracted from the calldata\\n /// @return receivingAssetId The receiving asset id extracted from the calldata\\n /// @return receivingAmount The receiving amount extracted from the calldata\\n function extractGenericSwapParameters(\\n bytes calldata data\\n )\\n public\\n pure\\n returns (\\n address sendingAssetId,\\n uint256 amount,\\n address receiver,\\n address receivingAssetId,\\n uint256 receivingAmount\\n )\\n {\\n LibSwap.SwapData[] memory swapData;\\n bytes memory callData = data;\\n\\n if (\\n bytes4(data[:4]) == StandardizedCallFacet.standardizedCall.selector\\n ) {\\n // standardizedCall\\n callData = abi.decode(data[4:], (bytes));\\n }\\n (, , , receiver, receivingAmount, swapData) = abi.decode(\\n callData.slice(4, callData.length - 4),\\n (bytes32, string, string, address, uint256, LibSwap.SwapData[])\\n );\\n\\n sendingAssetId = swapData[0].sendingAssetId;\\n amount = swapData[0].fromAmount;\\n receivingAssetId = swapData[swapData.length - 1].receivingAssetId;\\n return (\\n sendingAssetId,\\n amount,\\n receiver,\\n receivingAssetId,\\n receivingAmount\\n );\\n }\\n\\n /// @notice Validates the calldata\\n /// @param data The calldata to validate\\n /// @param bridge The bridge to validate or empty string to ignore\\n /// @param sendingAssetId The sending asset id to validate\\n /// or 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF to ignore\\n /// @param receiver The receiver to validate\\n /// or 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF to ignore\\n /// @param amount The amount to validate or type(uint256).max to ignore\\n /// @param destinationChainId The destination chain id to validate\\n /// or type(uint256).max to ignore\\n /// @param hasSourceSwaps Whether the calldata has source swaps\\n /// @param hasDestinationCall Whether the calldata has a destination call\\n /// @return isValid Whether the calldata is validate\\n function validateCalldata(\\n bytes calldata data,\\n string calldata bridge,\\n address sendingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 destinationChainId,\\n bool hasSourceSwaps,\\n bool hasDestinationCall\\n ) external pure returns (bool isValid) {\\n ILiFi.BridgeData memory bridgeData;\\n (\\n bridgeData.bridge,\\n bridgeData.sendingAssetId,\\n bridgeData.receiver,\\n bridgeData.minAmount,\\n bridgeData.destinationChainId,\\n bridgeData.hasSourceSwaps,\\n bridgeData.hasDestinationCall\\n ) = extractMainParameters(data);\\n return\\n // Check bridge\\n (keccak256(abi.encodePacked(bridge)) ==\\n keccak256(abi.encodePacked(\\\"\\\")) ||\\n keccak256(abi.encodePacked(bridgeData.bridge)) ==\\n keccak256(abi.encodePacked(bridge))) &&\\n // Check sendingAssetId\\n (sendingAssetId == 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF ||\\n bridgeData.sendingAssetId == sendingAssetId) &&\\n // Check receiver\\n (receiver == 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF ||\\n bridgeData.receiver == receiver) &&\\n // Check amount\\n (amount == type(uint256).max || bridgeData.minAmount == amount) &&\\n // Check destinationChainId\\n (destinationChainId == type(uint256).max ||\\n bridgeData.destinationChainId == destinationChainId) &&\\n // Check hasSourceSwaps\\n bridgeData.hasSourceSwaps == hasSourceSwaps &&\\n // Check hasDestinationCall\\n bridgeData.hasDestinationCall == hasDestinationCall;\\n }\\n\\n /// @notice Validates the destination calldata\\n /// @param data The calldata to validate\\n /// @param callTo The call to address to validate\\n /// @param dstCalldata The destination calldata to validate\\n /// @return isValid Whether the destination calldata is validate\\n function validateDestinationCalldata(\\n bytes calldata data,\\n bytes calldata callTo,\\n bytes calldata dstCalldata\\n ) external pure returns (bool isValid) {\\n bytes memory callData = data;\\n\\n // Handle standardizedCall\\n if (\\n bytes4(data[:4]) == StandardizedCallFacet.standardizedCall.selector\\n ) {\\n callData = abi.decode(data[4:], (bytes));\\n }\\n\\n bytes4 selector = abi.decode(callData, (bytes4));\\n\\n // Case: Amarok\\n if (selector == AmarokFacet.startBridgeTokensViaAmarok.selector) {\\n (, AmarokFacet.AmarokData memory amarokData) = abi.decode(\\n callData.slice(4, callData.length - 4),\\n (ILiFi.BridgeData, AmarokFacet.AmarokData)\\n );\\n\\n return\\n keccak256(dstCalldata) == keccak256(amarokData.callData) &&\\n abi.decode(callTo, (address)) == amarokData.callTo;\\n }\\n if (\\n selector == AmarokFacet.swapAndStartBridgeTokensViaAmarok.selector\\n ) {\\n (, , AmarokFacet.AmarokData memory amarokData) = abi.decode(\\n callData.slice(4, callData.length - 4),\\n (ILiFi.BridgeData, LibSwap.SwapData[], AmarokFacet.AmarokData)\\n );\\n return\\n keccak256(dstCalldata) == keccak256(amarokData.callData) &&\\n abi.decode(callTo, (address)) == amarokData.callTo;\\n }\\n\\n // Case: Stargate\\n if (selector == StargateFacet.startBridgeTokensViaStargate.selector) {\\n (, StargateFacet.StargateData memory stargateData) = abi.decode(\\n callData.slice(4, callData.length - 4),\\n (ILiFi.BridgeData, StargateFacet.StargateData)\\n );\\n return\\n keccak256(dstCalldata) == keccak256(stargateData.callData) &&\\n keccak256(callTo) == keccak256(stargateData.callTo);\\n }\\n if (\\n selector ==\\n StargateFacet.swapAndStartBridgeTokensViaStargate.selector\\n ) {\\n (, , StargateFacet.StargateData memory stargateData) = abi.decode(\\n callData.slice(4, callData.length - 4),\\n (\\n ILiFi.BridgeData,\\n LibSwap.SwapData[],\\n StargateFacet.StargateData\\n )\\n );\\n return\\n keccak256(dstCalldata) == keccak256(stargateData.callData) &&\\n keccak256(callTo) == keccak256(stargateData.callTo);\\n }\\n // Case: Celer\\n if (\\n selector == CelerIMFacetBase.startBridgeTokensViaCelerIM.selector\\n ) {\\n (, CelerIM.CelerIMData memory celerIMData) = abi.decode(\\n callData.slice(4, callData.length - 4),\\n (ILiFi.BridgeData, CelerIM.CelerIMData)\\n );\\n return\\n keccak256(dstCalldata) == keccak256(celerIMData.callData) &&\\n keccak256(callTo) == keccak256(celerIMData.callTo);\\n }\\n if (\\n selector ==\\n CelerIMFacetBase.swapAndStartBridgeTokensViaCelerIM.selector\\n ) {\\n (, , CelerIM.CelerIMData memory celerIMData) = abi.decode(\\n callData.slice(4, callData.length - 4),\\n (ILiFi.BridgeData, LibSwap.SwapData[], CelerIM.CelerIMData)\\n );\\n return\\n keccak256(dstCalldata) == keccak256(celerIMData.callData) &&\\n keccak256(callTo) == keccak256(celerIMData.callTo);\\n }\\n\\n // All other cases\\n return false;\\n }\\n\\n /// Internal Methods ///\\n\\n /// @notice Extracts the bridge data from the calldata\\n /// @param data The calldata to extract the bridge data from\\n /// @return bridgeData The bridge data extracted from the calldata\\n function _extractBridgeData(\\n bytes calldata data\\n ) internal pure returns (ILiFi.BridgeData memory bridgeData) {\\n if (\\n bytes4(data[:4]) == StandardizedCallFacet.standardizedCall.selector\\n ) {\\n // StandardizedCall\\n bytes memory unwrappedData = abi.decode(data[4:], (bytes));\\n bridgeData = abi.decode(\\n unwrappedData.slice(4, unwrappedData.length - 4),\\n (ILiFi.BridgeData)\\n );\\n return bridgeData;\\n }\\n // normal call\\n bridgeData = abi.decode(data[4:], (ILiFi.BridgeData));\\n }\\n\\n /// @notice Extracts the swap data from the calldata\\n /// @param data The calldata to extract the swap data from\\n /// @return swapData The swap data extracted from the calldata\\n function _extractSwapData(\\n bytes calldata data\\n ) internal pure returns (LibSwap.SwapData[] memory swapData) {\\n if (\\n bytes4(data[:4]) == StandardizedCallFacet.standardizedCall.selector\\n ) {\\n // standardizedCall\\n bytes memory unwrappedData = abi.decode(data[4:], (bytes));\\n (, swapData) = abi.decode(\\n unwrappedData.slice(4, unwrappedData.length - 4),\\n (ILiFi.BridgeData, LibSwap.SwapData[])\\n );\\n return swapData;\\n }\\n // normal call\\n (, swapData) = abi.decode(\\n data[4:],\\n (ILiFi.BridgeData, LibSwap.SwapData[])\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Facets/AmarokFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IConnextHandler } from \\\"../Interfaces/IConnextHandler.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { InformationMismatch } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title Amarok Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Connext Amarok\\n/// @custom:version 2.0.0\\ncontract AmarokFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n /// @notice The contract address of the connext handler on the source chain.\\n IConnextHandler private immutable connextHandler;\\n\\n /// @param callData The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.\\n /// @param callTo The address of the contract on dest chain that will receive bridged funds and execute data\\n /// @param relayerFee The amount of relayer fee the tx called xcall with\\n /// @param slippageTol Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)\\n /// @param delegate Destination delegate address\\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\\n /// @param payFeeWithSendingAsset Whether to pay the relayer fee with the sending asset or not\\n struct AmarokData {\\n bytes callData;\\n address callTo;\\n uint256 relayerFee;\\n uint256 slippageTol;\\n address delegate;\\n uint32 destChainDomainId;\\n bool payFeeWithSendingAsset;\\n }\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _connextHandler The contract address of the connext handler on the source chain.\\n constructor(IConnextHandler _connextHandler) {\\n connextHandler = _connextHandler;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Amarok\\n /// @param _bridgeData Data containing core information for bridging\\n /// @param _amarokData Data specific to bridge\\n function startBridgeTokensViaAmarok(\\n BridgeData calldata _bridgeData,\\n AmarokData calldata _amarokData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n noNativeAsset(_bridgeData)\\n {\\n validateDestinationCallFlag(_bridgeData, _amarokData);\\n\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n\\n _startBridge(_bridgeData, _amarokData);\\n }\\n\\n /// @notice Performs a swap before bridging via Amarok\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _amarokData Data specific to Amarok\\n function swapAndStartBridgeTokensViaAmarok(\\n BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n AmarokData calldata _amarokData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n noNativeAsset(_bridgeData)\\n {\\n validateDestinationCallFlag(_bridgeData, _amarokData);\\n\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n _amarokData.relayerFee\\n );\\n\\n _startBridge(_bridgeData, _amarokData);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Amarok\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _amarokData Data specific to Amarok\\n function _startBridge(\\n BridgeData memory _bridgeData,\\n AmarokData calldata _amarokData\\n ) private {\\n // give max approval for token to Amarok bridge, if not already\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(connextHandler),\\n _bridgeData.minAmount\\n );\\n\\n // initiate bridge transaction\\n if (_amarokData.payFeeWithSendingAsset) {\\n connextHandler.xcall(\\n _amarokData.destChainDomainId,\\n _amarokData.callTo,\\n _bridgeData.sendingAssetId,\\n _amarokData.delegate,\\n _bridgeData.minAmount - _amarokData.relayerFee,\\n _amarokData.slippageTol,\\n _amarokData.callData,\\n _amarokData.relayerFee\\n );\\n } else {\\n connextHandler.xcall{ value: _amarokData.relayerFee }(\\n _amarokData.destChainDomainId,\\n _amarokData.callTo,\\n _bridgeData.sendingAssetId,\\n _amarokData.delegate,\\n _bridgeData.minAmount,\\n _amarokData.slippageTol,\\n _amarokData.callData\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n function validateDestinationCallFlag(\\n ILiFi.BridgeData memory _bridgeData,\\n AmarokData calldata _amarokData\\n ) private pure {\\n if (\\n (_amarokData.callData.length > 0) != _bridgeData.hasDestinationCall\\n ) {\\n revert InformationMismatch();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Facets/StargateFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IStargateRouter } from \\\"../Interfaces/IStargateRouter.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { InformationMismatch, AlreadyInitialized, NotInitialized } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title Stargate Facet\\n/// @author Li.Finance (https://li.finance)\\n/// @notice Provides functionality for bridging through Stargate\\n/// @custom:version 2.1.0\\ncontract StargateFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// CONSTANTS ///\\n\\n /// @notice The contract address of the stargate router on the source chain.\\n IStargateRouter private immutable router;\\n /// @notice The contract address of the native stargate router on the source chain.\\n IStargateRouter private immutable nativeRouter;\\n /// @notice The contract address of the stargate composer on the source chain.\\n IStargateRouter private immutable composer;\\n\\n /// Storage ///\\n\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.facets.stargate\\\");\\n\\n /// Types ///\\n\\n struct Storage {\\n mapping(uint256 => uint16) layerZeroChainId;\\n bool initialized;\\n }\\n\\n struct ChainIdConfig {\\n uint256 chainId;\\n uint16 layerZeroChainId;\\n }\\n\\n /// @param srcPoolId Source pool id.\\n /// @param dstPoolId Dest pool id.\\n /// @param minAmountLD The min qty you would accept on the destination.\\n /// @param dstGasForCall Additional gas fee for extral call on the destination.\\n /// @param lzFee Estimated message fee.\\n /// @param refundAddress Refund adddress. Extra gas (if any) is returned to this address\\n /// @param callTo The address to send the tokens to on the destination.\\n /// @param callData Additional payload.\\n struct StargateData {\\n uint256 srcPoolId;\\n uint256 dstPoolId;\\n uint256 minAmountLD;\\n uint256 dstGasForCall;\\n uint256 lzFee;\\n address payable refundAddress;\\n bytes callTo;\\n bytes callData;\\n }\\n\\n /// Errors ///\\n\\n error UnknownLayerZeroChain();\\n\\n /// Events ///\\n\\n event StargateInitialized(ChainIdConfig[] chainIdConfigs);\\n\\n event LayerZeroChainIdSet(\\n uint256 indexed chainId,\\n uint16 layerZeroChainId\\n );\\n\\n /// @notice Emit to get credited for referral\\n /// @dev Our partner id is 0x0006\\n event PartnerSwap(bytes2 partnerId);\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _router The contract address of the stargate router on the source chain.\\n /// @param _nativeRouter The contract address of the native token stargate router on the source chain.\\n constructor(\\n IStargateRouter _router,\\n IStargateRouter _nativeRouter,\\n IStargateRouter _composer\\n ) {\\n router = _router;\\n nativeRouter = _nativeRouter;\\n composer = _composer;\\n }\\n\\n /// Init ///\\n\\n /// @notice Initialize local variables for the Stargate Facet\\n /// @param chainIdConfigs Chain Id configuration data\\n function initStargate(ChainIdConfig[] calldata chainIdConfigs) external {\\n LibDiamond.enforceIsContractOwner();\\n\\n Storage storage sm = getStorage();\\n\\n for (uint256 i = 0; i < chainIdConfigs.length; i++) {\\n sm.layerZeroChainId[chainIdConfigs[i].chainId] = chainIdConfigs[i]\\n .layerZeroChainId;\\n }\\n\\n sm.initialized = true;\\n\\n emit StargateInitialized(chainIdConfigs);\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Stargate Bridge\\n /// @param _bridgeData Data used purely for tracking and analytics\\n /// @param _stargateData Data specific to Stargate Bridge\\n function startBridgeTokensViaStargate(\\n ILiFi.BridgeData calldata _bridgeData,\\n StargateData calldata _stargateData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n validateDestinationCallFlag(_bridgeData, _stargateData);\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData, _stargateData);\\n }\\n\\n /// @notice Performs a swap before bridging via Stargate Bridge\\n /// @param _bridgeData Data used purely for tracking and analytics\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _stargateData Data specific to Stargate Bridge\\n function swapAndStartBridgeTokensViaStargate(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n StargateData calldata _stargateData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n validateDestinationCallFlag(_bridgeData, _stargateData);\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n LibAsset.isNativeAsset(_bridgeData.sendingAssetId)\\n ? 0\\n : _stargateData.lzFee\\n );\\n\\n _startBridge(_bridgeData, _stargateData);\\n }\\n\\n function quoteLayerZeroFee(\\n uint256 _destinationChainId,\\n StargateData calldata _stargateData\\n ) external view returns (uint256, uint256) {\\n // Transfers with callData have to be routed via the composer which adds additional overhead in fees.\\n // The composer exposes the same function as the router to calculate those fees.\\n IStargateRouter stargate = _stargateData.callData.length > 0\\n ? composer\\n : router;\\n return\\n stargate.quoteLayerZeroFee(\\n getLayerZeroChainId(_destinationChainId),\\n 1, // TYPE_SWAP_REMOTE on Bridge\\n _stargateData.callTo,\\n _stargateData.callData,\\n IStargateRouter.lzTxObj(\\n _stargateData.dstGasForCall,\\n 0,\\n toBytes(address(0))\\n )\\n );\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Stargate Bridge\\n /// @param _bridgeData Data used purely for tracking and analytics\\n /// @param _stargateData Data specific to Stargate Bridge\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n StargateData calldata _stargateData\\n ) private {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // All transfers with destination calls need to be routed via the composer contract\\n IStargateRouter stargate = _bridgeData.hasDestinationCall\\n ? composer\\n : nativeRouter;\\n\\n stargate.swapETHAndCall{ value: _bridgeData.minAmount }(\\n getLayerZeroChainId(_bridgeData.destinationChainId),\\n _stargateData.refundAddress,\\n _stargateData.callTo,\\n IStargateRouter.SwapAmount(\\n _bridgeData.minAmount - _stargateData.lzFee,\\n _stargateData.minAmountLD\\n ),\\n IStargateRouter.lzTxObj(\\n _stargateData.dstGasForCall,\\n 0,\\n toBytes(address(0))\\n ),\\n _stargateData.callData\\n );\\n } else {\\n // All transfers with destination calls need to be routed via the composer contract\\n IStargateRouter stargate = _bridgeData.hasDestinationCall\\n ? composer\\n : router;\\n\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(stargate),\\n _bridgeData.minAmount\\n );\\n\\n stargate.swap{ value: _stargateData.lzFee }(\\n getLayerZeroChainId(_bridgeData.destinationChainId),\\n _stargateData.srcPoolId,\\n _stargateData.dstPoolId,\\n _stargateData.refundAddress,\\n _bridgeData.minAmount,\\n _stargateData.minAmountLD,\\n IStargateRouter.lzTxObj(\\n _stargateData.dstGasForCall,\\n 0,\\n toBytes(address(0))\\n ),\\n _stargateData.callTo,\\n _stargateData.callData\\n );\\n }\\n\\n emit PartnerSwap(0x0006);\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n function validateDestinationCallFlag(\\n ILiFi.BridgeData memory _bridgeData,\\n StargateData calldata _stargateData\\n ) private pure {\\n if (\\n (_stargateData.callData.length > 0) !=\\n _bridgeData.hasDestinationCall\\n ) {\\n revert InformationMismatch();\\n }\\n }\\n\\n /// Mappings management ///\\n\\n /// @notice Sets the Layer 0 chain ID for a given chain ID\\n /// @param _chainId uint16 of the chain ID\\n /// @param _layerZeroChainId uint16 of the Layer 0 chain ID\\n /// @dev This is used to map a chain ID to its Layer 0 chain ID\\n function setLayerZeroChainId(\\n uint256 _chainId,\\n uint16 _layerZeroChainId\\n ) external {\\n LibDiamond.enforceIsContractOwner();\\n Storage storage sm = getStorage();\\n\\n if (!sm.initialized) {\\n revert NotInitialized();\\n }\\n\\n sm.layerZeroChainId[_chainId] = _layerZeroChainId;\\n emit LayerZeroChainIdSet(_chainId, _layerZeroChainId);\\n }\\n\\n /// @notice Gets the Layer 0 chain ID for a given chain ID\\n /// @param _chainId uint256 of the chain ID\\n /// @return uint16 of the Layer 0 chain ID\\n function getLayerZeroChainId(\\n uint256 _chainId\\n ) private view returns (uint16) {\\n Storage storage sm = getStorage();\\n uint16 chainId = sm.layerZeroChainId[_chainId];\\n if (chainId == 0) revert UnknownLayerZeroChain();\\n return chainId;\\n }\\n\\n function toBytes(address _address) private pure returns (bytes memory) {\\n return abi.encodePacked(_address);\\n }\\n\\n /// @dev fetch local storage\\n function getStorage() private pure returns (Storage storage s) {\\n bytes32 namespace = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n s.slot := namespace\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/CelerIMFacetBase.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ERC20 } from \\\"solmate/tokens/ERC20.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { InvalidAmount, InformationMismatch } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { MessageSenderLib, MsgDataTypes, IMessageBus } from \\\"celer-network/contracts/message/libraries/MessageSenderLib.sol\\\";\\nimport { RelayerCelerIM } from \\\"lifi/Periphery/RelayerCelerIM.sol\\\";\\n\\ninterface CelerToken {\\n function canonical() external returns (address);\\n}\\n\\ninterface CelerIM {\\n /// @param maxSlippage The max slippage accepted, given as percentage in point (pip).\\n /// @param nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\\n /// @param callTo The address of the contract to be called at destination.\\n /// @param callData The encoded calldata with below data\\n /// bytes32 transactionId,\\n /// LibSwap.SwapData[] memory swapData,\\n /// address receiver,\\n /// address refundAddress\\n /// @param messageBusFee The fee to be paid to CBridge message bus for relaying the message\\n /// @param bridgeType Defines the bridge operation type (must be one of the values of CBridge library MsgDataTypes.BridgeSendType)\\n struct CelerIMData {\\n uint32 maxSlippage;\\n uint64 nonce;\\n bytes callTo;\\n bytes callData;\\n uint256 messageBusFee;\\n MsgDataTypes.BridgeSendType bridgeType;\\n }\\n}\\n\\n/// @title CelerIM Facet Base\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging tokens and data through CBridge\\n/// @notice Used to differentiate between contract instances for mutable and immutable diamond as these cannot be shared\\n/// @custom:version 2.0.0\\nabstract contract CelerIMFacetBase is\\n ILiFi,\\n ReentrancyGuard,\\n SwapperV2,\\n Validatable\\n{\\n /// Storage ///\\n\\n /// @dev The contract address of the cBridge Message Bus\\n IMessageBus private immutable cBridgeMessageBus;\\n\\n /// @dev The contract address of the RelayerCelerIM\\n RelayerCelerIM public immutable relayer;\\n\\n /// @dev The contract address of the Celer Flow USDC\\n address private immutable cfUSDC;\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _messageBus The contract address of the cBridge Message Bus\\n /// @param _relayerOwner The address that will become the owner of the RelayerCelerIM contract\\n /// @param _diamondAddress The address of the diamond contract that will be connected with the RelayerCelerIM\\n /// @param _cfUSDC The contract address of the Celer Flow USDC\\n constructor(\\n IMessageBus _messageBus,\\n address _relayerOwner,\\n address _diamondAddress,\\n address _cfUSDC\\n ) {\\n // deploy RelayerCelerIM\\n relayer = new RelayerCelerIM(\\n address(_messageBus),\\n _relayerOwner,\\n _diamondAddress\\n );\\n\\n // store arguments in variables\\n cBridgeMessageBus = _messageBus;\\n cfUSDC = _cfUSDC;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via CBridge\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _celerIMData Data specific to CelerIM\\n function startBridgeTokensViaCelerIM(\\n ILiFi.BridgeData memory _bridgeData,\\n CelerIM.CelerIMData calldata _celerIMData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n validateDestinationCallFlag(_bridgeData, _celerIMData);\\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // Transfer ERC20 tokens directly to relayer\\n IERC20 asset = _getRightAsset(_bridgeData.sendingAssetId);\\n\\n // Deposit ERC20 token\\n uint256 prevBalance = asset.balanceOf(address(relayer));\\n SafeERC20.safeTransferFrom(\\n asset,\\n msg.sender,\\n address(relayer),\\n _bridgeData.minAmount\\n );\\n\\n if (\\n asset.balanceOf(address(relayer)) - prevBalance !=\\n _bridgeData.minAmount\\n ) {\\n revert InvalidAmount();\\n }\\n }\\n\\n _startBridge(_bridgeData, _celerIMData);\\n }\\n\\n /// @notice Performs a swap before bridging via CBridge\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _celerIMData Data specific to CelerIM\\n function swapAndStartBridgeTokensViaCelerIM(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n CelerIM.CelerIMData calldata _celerIMData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n validateDestinationCallFlag(_bridgeData, _celerIMData);\\n\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n _celerIMData.messageBusFee\\n );\\n\\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // Transfer ERC20 tokens directly to relayer\\n IERC20 asset = _getRightAsset(_bridgeData.sendingAssetId);\\n\\n // Deposit ERC20 token\\n uint256 prevBalance = asset.balanceOf(address(relayer));\\n SafeERC20.safeTransfer(\\n asset,\\n address(relayer),\\n _bridgeData.minAmount\\n );\\n\\n if (\\n asset.balanceOf(address(relayer)) - prevBalance !=\\n _bridgeData.minAmount\\n ) {\\n revert InvalidAmount();\\n }\\n }\\n\\n _startBridge(_bridgeData, _celerIMData);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via CBridge\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _celerIMData Data specific to CBridge\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n CelerIM.CelerIMData calldata _celerIMData\\n ) private {\\n // Assuming messageBusFee is pre-calculated off-chain and available in _celerIMData\\n // Determine correct native asset amount to be forwarded (if so) and send funds to relayer\\n uint256 msgValue = LibAsset.isNativeAsset(_bridgeData.sendingAssetId)\\n ? _bridgeData.minAmount\\n : 0;\\n\\n // Check if transaction contains a destination call\\n if (!_bridgeData.hasDestinationCall) {\\n // Case 'no': Simple bridge transfer - Send to receiver\\n relayer.sendTokenTransfer{ value: msgValue }(\\n _bridgeData,\\n _celerIMData\\n );\\n } else {\\n // Case 'yes': Bridge + Destination call - Send to relayer\\n\\n // save address of original recipient\\n address receiver = _bridgeData.receiver;\\n\\n // Set relayer as a receiver\\n _bridgeData.receiver = address(relayer);\\n\\n // send token transfer\\n (bytes32 transferId, address bridgeAddress) = relayer\\n .sendTokenTransfer{ value: msgValue }(\\n _bridgeData,\\n _celerIMData\\n );\\n\\n // Call message bus via relayer incl messageBusFee\\n relayer.forwardSendMessageWithTransfer{\\n value: _celerIMData.messageBusFee\\n }(\\n _bridgeData.receiver,\\n uint64(_bridgeData.destinationChainId),\\n bridgeAddress,\\n transferId,\\n _celerIMData.callData\\n );\\n\\n // Reset receiver of bridge data for event emission\\n _bridgeData.receiver = receiver;\\n }\\n\\n // emit LiFi event\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @dev Get right asset to transfer to relayer.\\n /// @param _sendingAssetId The address of asset to bridge.\\n /// @return _asset The address of asset to transfer to relayer.\\n function _getRightAsset(\\n address _sendingAssetId\\n ) private returns (IERC20 _asset) {\\n if (_sendingAssetId == cfUSDC) {\\n // special case for cfUSDC token\\n _asset = IERC20(CelerToken(_sendingAssetId).canonical());\\n } else {\\n // any other ERC20 token\\n _asset = IERC20(_sendingAssetId);\\n }\\n }\\n\\n function validateDestinationCallFlag(\\n ILiFi.BridgeData memory _bridgeData,\\n CelerIM.CelerIMData calldata _celerIMData\\n ) private pure {\\n if (\\n (_celerIMData.callData.length > 0) !=\\n _bridgeData.hasDestinationCall\\n ) {\\n revert InformationMismatch();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Facets/StandardizedCallFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\n\\n/// @title Standardized Call Facet\\n/// @author LIFI https://li.finance ed@li.finance\\n/// @notice Allows calling different facet methods through a single standardized entrypoint\\n/// @custom:version 1.0.0\\ncontract StandardizedCallFacet {\\n /// External Methods ///\\n\\n /// @notice Make a standardized call to a facet\\n /// @param callData The calldata to forward to the facet\\n function standardizedCall(bytes memory callData) external payable {\\n // Fetch the facetAddress from the dimaond's internal storage\\n // Cheaper than calling the external facetAddress(selector) method directly\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n address facetAddress = ds\\n .selectorToFacetAndPosition[bytes4(callData)]\\n .facetAddress;\\n\\n if (facetAddress == address(0)) {\\n revert LibDiamond.FunctionDoesNotExist();\\n }\\n\\n // Execute external function from facet using delegatecall and return any value.\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n // execute function call using the facet\\n let result := delegatecall(\\n gas(),\\n facetAddress,\\n add(callData, 0x20),\\n mload(callData),\\n 0,\\n 0\\n )\\n // get any return value\\n returndatacopy(0, 0, returndatasize())\\n // return any return value or error back to the caller\\n switch result\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Interfaces/IConnextHandler.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IConnextHandler {\\n /// @notice These are the call parameters that will remain constant between the\\n /// two chains. They are supplied on `xcall` and should be asserted on `execute`\\n /// @property to - The account that receives funds, in the event of a crosschain call,\\n /// will receive funds if the call fails.\\n /// @param to - The address you are sending funds (and potentially data) to\\n /// @param callData - The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.\\n /// @param originDomain - The originating domain (i.e. where `xcall` is called). Must match nomad domain schema\\n /// @param destinationDomain - The final domain (i.e. where `execute` / `reconcile` are called). Must match nomad domain schema\\n /// @param agent - An address who can execute txs on behalf of `to`, in addition to allowing relayers\\n /// @param recovery - The address to send funds to if your `Executor.execute call` fails\\n /// @param forceSlow - If true, will take slow liquidity path even if it is not a permissioned call\\n /// @param receiveLocal - If true, will use the local nomad asset on the destination instead of adopted.\\n /// @param callback - The address on the origin domain of the callback contract\\n /// @param callbackFee - The relayer fee to execute the callback\\n /// @param relayerFee - The amount of relayer fee the tx called xcall with\\n /// @param slippageTol - Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)\\n struct CallParams {\\n address to;\\n bytes callData;\\n uint32 originDomain;\\n uint32 destinationDomain;\\n address agent;\\n address recovery;\\n bool forceSlow;\\n bool receiveLocal;\\n address callback;\\n uint256 callbackFee;\\n uint256 relayerFee;\\n uint256 slippageTol;\\n }\\n\\n /// @notice The arguments you supply to the `xcall` function called by user on origin domain\\n /// @param params - The CallParams. These are consistent across sending and receiving chains\\n /// @param transactingAsset - The asset the caller sent with the transfer. Can be the adopted, canonical,\\n /// or the representational asset\\n /// @param transactingAmount - The amount of transferring asset supplied by the user in the `xcall`\\n /// @param originMinOut - Minimum amount received on swaps for adopted <> local on origin chain\\n struct XCallArgs {\\n CallParams params;\\n address transactingAsset; // Could be adopted, local, or wrapped\\n uint256 transactingAmount;\\n uint256 originMinOut;\\n }\\n\\n function xcall(\\n uint32 destination,\\n address recipient,\\n address tokenAddress,\\n address delegate,\\n uint256 amount,\\n uint256 slippage,\\n bytes memory callData\\n ) external payable returns (bytes32);\\n\\n function xcall(\\n uint32 destination,\\n address recipient,\\n address tokenAddress,\\n address delegate,\\n uint256 amount,\\n uint256 slippage,\\n bytes memory callData,\\n uint256 _relayerFee\\n ) external returns (bytes32);\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IStargateRouter.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity 0.8.17;\\n\\n// solhint-disable contract-name-camelcase\\ninterface IStargateRouter {\\n struct lzTxObj {\\n uint256 dstGasForCall;\\n uint256 dstNativeAmount;\\n bytes dstNativeAddr;\\n }\\n\\n /// @notice SwapAmount struct\\n /// @param amountLD The amount, in Local Decimals, to be swapped\\n /// @param minAmountLD The minimum amount accepted out on destination\\n struct SwapAmount {\\n uint256 amountLD;\\n uint256 minAmountLD;\\n }\\n\\n /// @notice Returns factory address used for creating pools.\\n function factory() external view returns (address);\\n\\n /// @notice Swap assets cross-chain.\\n /// @dev Pass (0, 0, \\\"0x\\\") to lzTxParams\\n /// for 0 additional gasLimit increase, 0 airdrop, at 0x address.\\n /// @param dstChainId Destination chainId\\n /// @param srcPoolId Source pool id\\n /// @param dstPoolId Dest pool id\\n /// @param refundAddress Refund adddress. extra gas (if any) is returned to this address\\n /// @param amountLD Quantity to swap\\n /// @param minAmountLD The min qty you would accept on the destination\\n /// @param lzTxParams Additional gas, airdrop data\\n /// @param to The address to send the tokens to on the destination\\n /// @param payload Additional payload. You can abi.encode() them here\\n function swap(\\n uint16 dstChainId,\\n uint256 srcPoolId,\\n uint256 dstPoolId,\\n address payable refundAddress,\\n uint256 amountLD,\\n uint256 minAmountLD,\\n lzTxObj memory lzTxParams,\\n bytes calldata to,\\n bytes calldata payload\\n ) external payable;\\n\\n /// @notice Swap native assets cross-chain.\\n /// @param _dstChainId Destination Stargate chainId\\n /// @param _refundAddress Refunds additional messageFee to this address\\n /// @param _toAddress The receiver of the destination ETH\\n /// @param _swapAmount The amount and the minimum swap amount\\n /// @param _lzTxParams The LZ tx params\\n /// @param _payload The payload to send to the destination\\n function swapETHAndCall(\\n uint16 _dstChainId,\\n address payable _refundAddress,\\n bytes calldata _toAddress,\\n SwapAmount memory _swapAmount,\\n IStargateRouter.lzTxObj memory _lzTxParams,\\n bytes calldata _payload\\n ) external payable;\\n\\n /// @notice Returns the native gas fee required for swap.\\n function quoteLayerZeroFee(\\n uint16 dstChainId,\\n uint8 functionType,\\n bytes calldata toAddress,\\n bytes calldata transferAndCallPayload,\\n lzTxObj memory lzTxParams\\n ) external view returns (uint256 nativeFee, uint256 zroFee);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/solmate/src/tokens/ERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\\nabstract contract ERC20 {\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /*//////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string public name;\\n\\n string public symbol;\\n\\n uint8 public immutable decimals;\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 public totalSupply;\\n\\n mapping(address => uint256) public balanceOf;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 internal immutable INITIAL_CHAIN_ID;\\n\\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\\n\\n mapping(address => uint256) public nonces;\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n constructor(\\n string memory _name,\\n string memory _symbol,\\n uint8 _decimals\\n ) {\\n name = _name;\\n symbol = _symbol;\\n decimals = _decimals;\\n\\n INITIAL_CHAIN_ID = block.chainid;\\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function approve(address spender, uint256 amount) public virtual returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n\\n return true;\\n }\\n\\n function transfer(address to, uint256 amount) public virtual returns (bool) {\\n balanceOf[msg.sender] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(msg.sender, to, amount);\\n\\n return true;\\n }\\n\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual returns (bool) {\\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\\n\\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\\n\\n balanceOf[from] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n return true;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 LOGIC\\n //////////////////////////////////////////////////////////////*/\\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 ) public virtual {\\n require(deadline >= block.timestamp, \\\"PERMIT_DEADLINE_EXPIRED\\\");\\n\\n // Unchecked because the only math done is incrementing\\n // the owner's nonce which cannot realistically overflow.\\n unchecked {\\n address recoveredAddress = ecrecover(\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR(),\\n keccak256(\\n abi.encode(\\n keccak256(\\n \\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\"\\n ),\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n require(recoveredAddress != address(0) && recoveredAddress == owner, \\\"INVALID_SIGNER\\\");\\n\\n allowance[recoveredAddress][spender] = value;\\n }\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\\n }\\n\\n function computeDomainSeparator() internal view virtual returns (bytes32) {\\n return\\n keccak256(\\n abi.encode(\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"),\\n keccak256(bytes(name)),\\n keccak256(\\\"1\\\"),\\n block.chainid,\\n address(this)\\n )\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _mint(address to, uint256 amount) internal virtual {\\n totalSupply += amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(address(0), to, amount);\\n }\\n\\n function _burn(address from, uint256 amount) internal virtual {\\n balanceOf[from] -= amount;\\n\\n // Cannot underflow because a user's balance\\n // will never be larger than the total supply.\\n unchecked {\\n totalSupply -= amount;\\n }\\n\\n emit Transfer(from, address(0), amount);\\n }\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/message/libraries/MessageSenderLib.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"../../interfaces/IBridge.sol\\\";\\nimport \\\"../../interfaces/IOriginalTokenVault.sol\\\";\\nimport \\\"../../interfaces/IOriginalTokenVaultV2.sol\\\";\\nimport \\\"../../interfaces/IPeggedTokenBridge.sol\\\";\\nimport \\\"../../interfaces/IPeggedTokenBridgeV2.sol\\\";\\nimport \\\"../interfaces/IMessageBus.sol\\\";\\nimport \\\"./MsgDataTypes.sol\\\";\\n\\nlibrary MessageSenderLib {\\n using SafeERC20 for IERC20;\\n\\n // ============== Internal library functions called by apps ==============\\n\\n /**\\n * @notice Sends a message to an app on another chain via MessageBus without an associated transfer.\\n * @param _receiver The address of the destination app contract.\\n * @param _dstChainId The destination chain ID.\\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\\n * @param _messageBus The address of the MessageBus on this chain.\\n * @param _fee The fee amount to pay to MessageBus.\\n */\\n function sendMessage(\\n address _receiver,\\n uint64 _dstChainId,\\n bytes memory _message,\\n address _messageBus,\\n uint256 _fee\\n ) internal {\\n IMessageBus(_messageBus).sendMessage{value: _fee}(_receiver, _dstChainId, _message);\\n }\\n\\n // Send message to non-evm chain with bytes for receiver address,\\n // otherwise same as above.\\n function sendMessage(\\n bytes calldata _receiver,\\n uint64 _dstChainId,\\n bytes memory _message,\\n address _messageBus,\\n uint256 _fee\\n ) internal {\\n IMessageBus(_messageBus).sendMessage{value: _fee}(_receiver, _dstChainId, _message);\\n }\\n\\n /**\\n * @notice Sends a message to an app on another chain via MessageBus with an associated transfer.\\n * @param _receiver The address of the destination app contract.\\n * @param _token The address of the token to be sent.\\n * @param _amount The amount of tokens to be sent.\\n * @param _dstChainId The destination chain ID.\\n * @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\\n * @param _maxSlippage The max slippage accepted, given as percentage in point (pip). Eg. 5000 means 0.5%.\\n * Must be greater than minimalMaxSlippage. Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount or the\\n * transfer can be refunded. Only applicable to the {MsgDataTypes.BridgeSendType.Liquidity}.\\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\\n * @param _bridgeSendType One of the {MsgDataTypes.BridgeSendType} enum.\\n * @param _messageBus The address of the MessageBus on this chain.\\n * @param _fee The fee amount to pay to MessageBus.\\n * @return The transfer ID.\\n */\\n function sendMessageWithTransfer(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce,\\n uint32 _maxSlippage,\\n bytes memory _message,\\n MsgDataTypes.BridgeSendType _bridgeSendType,\\n address _messageBus,\\n uint256 _fee\\n ) internal returns (bytes32) {\\n (bytes32 transferId, address bridge) = sendTokenTransfer(\\n _receiver,\\n _token,\\n _amount,\\n _dstChainId,\\n _nonce,\\n _maxSlippage,\\n _bridgeSendType,\\n _messageBus\\n );\\n if (_message.length > 0) {\\n IMessageBus(_messageBus).sendMessageWithTransfer{value: _fee}(\\n _receiver,\\n _dstChainId,\\n bridge,\\n transferId,\\n _message\\n );\\n }\\n return transferId;\\n }\\n\\n /**\\n * @notice Sends a token transfer via a bridge.\\n * @param _receiver The address of the destination app contract.\\n * @param _token The address of the token to be sent.\\n * @param _amount The amount of tokens to be sent.\\n * @param _dstChainId The destination chain ID.\\n * @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\\n * @param _maxSlippage The max slippage accepted, given as percentage in point (pip). Eg. 5000 means 0.5%.\\n * Must be greater than minimalMaxSlippage. Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount or the\\n * transfer can be refunded.\\n * @param _bridgeSendType One of the {MsgDataTypes.BridgeSendType} enum.\\n */\\n function sendTokenTransfer(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce,\\n uint32 _maxSlippage,\\n MsgDataTypes.BridgeSendType _bridgeSendType,\\n address _messageBus\\n ) internal returns (bytes32 transferId, address bridge) {\\n if (_bridgeSendType == MsgDataTypes.BridgeSendType.Liquidity) {\\n bridge = IMessageBus(_messageBus).liquidityBridge();\\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\\n IBridge(bridge).send(_receiver, _token, _amount, _dstChainId, _nonce, _maxSlippage);\\n transferId = computeLiqBridgeTransferId(_receiver, _token, _amount, _dstChainId, _nonce);\\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegDeposit) {\\n bridge = IMessageBus(_messageBus).pegVault();\\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\\n IOriginalTokenVault(bridge).deposit(_token, _amount, _dstChainId, _receiver, _nonce);\\n transferId = computePegV1DepositId(_receiver, _token, _amount, _dstChainId, _nonce);\\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegBurn) {\\n bridge = IMessageBus(_messageBus).pegBridge();\\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\\n IPeggedTokenBridge(bridge).burn(_token, _amount, _receiver, _nonce);\\n // handle cases where certain tokens do not spend allowance for role-based burn\\n IERC20(_token).safeApprove(bridge, 0);\\n transferId = computePegV1BurnId(_receiver, _token, _amount, _nonce);\\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2Deposit) {\\n bridge = IMessageBus(_messageBus).pegVaultV2();\\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\\n transferId = IOriginalTokenVaultV2(bridge).deposit(_token, _amount, _dstChainId, _receiver, _nonce);\\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2Burn) {\\n bridge = IMessageBus(_messageBus).pegBridgeV2();\\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\\n transferId = IPeggedTokenBridgeV2(bridge).burn(_token, _amount, _dstChainId, _receiver, _nonce);\\n // handle cases where certain tokens do not spend allowance for role-based burn\\n IERC20(_token).safeApprove(bridge, 0);\\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2BurnFrom) {\\n bridge = IMessageBus(_messageBus).pegBridgeV2();\\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\\n transferId = IPeggedTokenBridgeV2(bridge).burnFrom(_token, _amount, _dstChainId, _receiver, _nonce);\\n // handle cases where certain tokens do not spend allowance for role-based burn\\n IERC20(_token).safeApprove(bridge, 0);\\n } else {\\n revert(\\\"bridge type not supported\\\");\\n }\\n }\\n\\n function computeLiqBridgeTransferId(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce\\n ) internal view returns (bytes32) {\\n return\\n keccak256(\\n abi.encodePacked(address(this), _receiver, _token, _amount, _dstChainId, _nonce, uint64(block.chainid))\\n );\\n }\\n\\n function computePegV1DepositId(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce\\n ) internal view returns (bytes32) {\\n return\\n keccak256(\\n abi.encodePacked(address(this), _token, _amount, _dstChainId, _receiver, _nonce, uint64(block.chainid))\\n );\\n }\\n\\n function computePegV1BurnId(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _nonce\\n ) internal view returns (bytes32) {\\n return keccak256(abi.encodePacked(address(this), _token, _amount, _receiver, _nonce, uint64(block.chainid)));\\n }\\n}\\n\"\r\n },\r\n \"src/Periphery/RelayerCelerIM.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IERC20, SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { ContractCallNotAllowed, ExternalCallFailed, InvalidConfig, UnAuthorized, WithdrawFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { PeripheryRegistryFacet } from \\\"../Facets/PeripheryRegistryFacet.sol\\\";\\nimport { IExecutor } from \\\"../Interfaces/IExecutor.sol\\\";\\nimport { TransferrableOwnership } from \\\"../Helpers/TransferrableOwnership.sol\\\";\\nimport { IMessageReceiverApp } from \\\"celer-network/contracts/message/interfaces/IMessageReceiverApp.sol\\\";\\nimport { CelerIM } from \\\"lifi/Helpers/CelerIMFacetBase.sol\\\";\\nimport { MessageSenderLib, MsgDataTypes, IMessageBus, IOriginalTokenVault, IPeggedTokenBridge, IOriginalTokenVaultV2, IPeggedTokenBridgeV2 } from \\\"celer-network/contracts/message/libraries/MessageSenderLib.sol\\\";\\nimport { IBridge as ICBridge } from \\\"celer-network/contracts/interfaces/IBridge.sol\\\";\\n\\n/// @title RelayerCelerIM\\n/// @author LI.FI (https://li.fi)\\n/// @notice Relayer contract for CelerIM that forwards calls and handles refunds on src side and acts receiver on dest\\n/// @custom:version 2.0.0\\ncontract RelayerCelerIM is ILiFi, TransferrableOwnership {\\n using SafeERC20 for IERC20;\\n\\n /// Storage ///\\n\\n IMessageBus public cBridgeMessageBus;\\n address public diamondAddress;\\n\\n /// Events ///\\n\\n event LogWithdraw(\\n address indexed _assetAddress,\\n address indexed _to,\\n uint256 amount\\n );\\n\\n /// Modifiers ///\\n\\n modifier onlyCBridgeMessageBus() {\\n if (msg.sender != address(cBridgeMessageBus)) revert UnAuthorized();\\n _;\\n }\\n modifier onlyDiamond() {\\n if (msg.sender != diamondAddress) revert UnAuthorized();\\n _;\\n }\\n\\n /// Constructor\\n\\n constructor(\\n address _cBridgeMessageBusAddress,\\n address _owner,\\n address _diamondAddress\\n ) TransferrableOwnership(_owner) {\\n owner = _owner;\\n cBridgeMessageBus = IMessageBus(_cBridgeMessageBusAddress);\\n diamondAddress = _diamondAddress;\\n }\\n\\n /// External Methods ///\\n\\n /**\\n * @notice Called by MessageBus to execute a message with an associated token transfer.\\n * The Receiver is guaranteed to have received the right amount of tokens before this function is called.\\n * @param * (unused) The address of the source app contract\\n * @param _token The address of the token that comes out of the bridge\\n * @param _amount The amount of tokens received at this contract through the cross-chain bridge.\\n * @param * (unused) The source chain ID where the transfer is originated from\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param * (unused) Address who called the MessageBus execution function\\n */\\n function executeMessageWithTransfer(\\n address,\\n address _token,\\n uint256 _amount,\\n uint64,\\n bytes calldata _message,\\n address\\n )\\n external\\n payable\\n onlyCBridgeMessageBus\\n returns (IMessageReceiverApp.ExecutionStatus)\\n {\\n // decode message\\n (\\n bytes32 transactionId,\\n LibSwap.SwapData[] memory swapData,\\n address receiver,\\n address refundAddress\\n ) = abi.decode(\\n _message,\\n (bytes32, LibSwap.SwapData[], address, address)\\n );\\n\\n _swapAndCompleteBridgeTokens(\\n transactionId,\\n swapData,\\n _token,\\n payable(receiver),\\n _amount,\\n refundAddress\\n );\\n\\n return IMessageReceiverApp.ExecutionStatus.Success;\\n }\\n\\n /**\\n * @notice Called by MessageBus to process refund of the original transfer from this contract.\\n * The contract is guaranteed to have received the refund before this function is called.\\n * @param _token The token address of the original transfer\\n * @param _amount The amount of the original transfer\\n * @param _message The same message associated with the original transfer\\n * @param * (unused) Address who called the MessageBus execution function\\n */\\n function executeMessageWithTransferRefund(\\n address _token,\\n uint256 _amount,\\n bytes calldata _message,\\n address\\n )\\n external\\n payable\\n onlyCBridgeMessageBus\\n returns (IMessageReceiverApp.ExecutionStatus)\\n {\\n (bytes32 transactionId, , , address refundAddress) = abi.decode(\\n _message,\\n (bytes32, LibSwap.SwapData[], address, address)\\n );\\n\\n // return funds to cBridgeData.refundAddress\\n LibAsset.transferAsset(_token, payable(refundAddress), _amount);\\n\\n emit LiFiTransferRecovered(\\n transactionId,\\n _token,\\n refundAddress,\\n _amount,\\n block.timestamp\\n );\\n\\n return IMessageReceiverApp.ExecutionStatus.Success;\\n }\\n\\n /**\\n * @notice Forwards a call to transfer tokens to cBridge (sent via this contract to ensure that potential refunds are sent here)\\n * @param _bridgeData the core information needed for bridging\\n * @param _celerIMData data specific to CelerIM\\n */\\n // solhint-disable-next-line code-complexity\\n function sendTokenTransfer(\\n ILiFi.BridgeData memory _bridgeData,\\n CelerIM.CelerIMData calldata _celerIMData\\n )\\n external\\n payable\\n onlyDiamond\\n returns (bytes32 transferId, address bridgeAddress)\\n {\\n // approve to and call correct bridge depending on BridgeSendType\\n // @dev copied and slightly adapted from Celer MessageSenderLib\\n if (_celerIMData.bridgeType == MsgDataTypes.BridgeSendType.Liquidity) {\\n bridgeAddress = cBridgeMessageBus.liquidityBridge();\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // case: native asset bridging\\n ICBridge(bridgeAddress).sendNative{\\n value: _bridgeData.minAmount\\n }(\\n _bridgeData.receiver,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _celerIMData.nonce,\\n _celerIMData.maxSlippage\\n );\\n } else {\\n // case: ERC20 asset bridging\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n bridgeAddress,\\n _bridgeData.minAmount\\n );\\n // solhint-disable-next-line check-send-result\\n ICBridge(bridgeAddress).send(\\n _bridgeData.receiver,\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _celerIMData.nonce,\\n _celerIMData.maxSlippage\\n );\\n }\\n transferId = MessageSenderLib.computeLiqBridgeTransferId(\\n _bridgeData.receiver,\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _celerIMData.nonce\\n );\\n } else if (\\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegDeposit\\n ) {\\n bridgeAddress = cBridgeMessageBus.pegVault();\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n bridgeAddress,\\n _bridgeData.minAmount\\n );\\n IOriginalTokenVault(bridgeAddress).deposit(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _bridgeData.receiver,\\n _celerIMData.nonce\\n );\\n transferId = MessageSenderLib.computePegV1DepositId(\\n _bridgeData.receiver,\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _celerIMData.nonce\\n );\\n } else if (\\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegBurn\\n ) {\\n bridgeAddress = cBridgeMessageBus.pegBridge();\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n bridgeAddress,\\n _bridgeData.minAmount\\n );\\n IPeggedTokenBridge(bridgeAddress).burn(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n _bridgeData.receiver,\\n _celerIMData.nonce\\n );\\n transferId = MessageSenderLib.computePegV1BurnId(\\n _bridgeData.receiver,\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n _celerIMData.nonce\\n );\\n } else if (\\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegV2Deposit\\n ) {\\n bridgeAddress = cBridgeMessageBus.pegVaultV2();\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // case: native asset bridging\\n transferId = IOriginalTokenVaultV2(bridgeAddress)\\n .depositNative{ value: _bridgeData.minAmount }(\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _bridgeData.receiver,\\n _celerIMData.nonce\\n );\\n } else {\\n // case: ERC20 bridging\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n bridgeAddress,\\n _bridgeData.minAmount\\n );\\n transferId = IOriginalTokenVaultV2(bridgeAddress).deposit(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _bridgeData.receiver,\\n _celerIMData.nonce\\n );\\n }\\n } else if (\\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegV2Burn\\n ) {\\n bridgeAddress = cBridgeMessageBus.pegBridgeV2();\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n bridgeAddress,\\n _bridgeData.minAmount\\n );\\n transferId = IPeggedTokenBridgeV2(bridgeAddress).burn(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _bridgeData.receiver,\\n _celerIMData.nonce\\n );\\n } else if (\\n _celerIMData.bridgeType ==\\n MsgDataTypes.BridgeSendType.PegV2BurnFrom\\n ) {\\n bridgeAddress = cBridgeMessageBus.pegBridgeV2();\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n bridgeAddress,\\n _bridgeData.minAmount\\n );\\n transferId = IPeggedTokenBridgeV2(bridgeAddress).burnFrom(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n uint64(_bridgeData.destinationChainId),\\n _bridgeData.receiver,\\n _celerIMData.nonce\\n );\\n } else {\\n revert InvalidConfig();\\n }\\n }\\n\\n /**\\n * @notice Forwards a call to the CBridge Messagebus\\n * @param _receiver The address of the destination app contract.\\n * @param _dstChainId The destination chain ID.\\n * @param _srcBridge The bridge contract to send the transfer with.\\n * @param _srcTransferId The transfer ID.\\n * @param _dstChainId The destination chain ID.\\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\\n */\\n function forwardSendMessageWithTransfer(\\n address _receiver,\\n uint256 _dstChainId,\\n address _srcBridge,\\n bytes32 _srcTransferId,\\n bytes calldata _message\\n ) external payable onlyDiamond {\\n cBridgeMessageBus.sendMessageWithTransfer{ value: msg.value }(\\n _receiver,\\n _dstChainId,\\n _srcBridge,\\n _srcTransferId,\\n _message\\n );\\n }\\n\\n // ------------------------------------------------------------------------------------------------\\n\\n /// Private Methods ///\\n\\n /// @notice Performs a swap before completing a cross-chain transaction\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swapData array of data needed for swaps\\n /// @param assetId token received from the other chain\\n /// @param receiver address that will receive tokens in the end\\n /// @param amount amount of token\\n function _swapAndCompleteBridgeTokens(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] memory _swapData,\\n address assetId,\\n address payable receiver,\\n uint256 amount,\\n address refundAddress\\n ) private {\\n bool success;\\n IExecutor executor = IExecutor(\\n PeripheryRegistryFacet(diamondAddress).getPeripheryContract(\\n \\\"Executor\\\"\\n )\\n );\\n if (LibAsset.isNativeAsset(assetId)) {\\n try\\n executor.swapAndCompleteBridgeTokens{ value: amount }(\\n _transactionId,\\n _swapData,\\n assetId,\\n receiver\\n )\\n {\\n success = true;\\n } catch {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool fundsSent, ) = refundAddress.call{ value: amount }(\\\"\\\");\\n if (!fundsSent) {\\n revert ExternalCallFailed();\\n }\\n }\\n } else {\\n IERC20 token = IERC20(assetId);\\n token.safeApprove(address(executor), 0);\\n token.safeIncreaseAllowance(address(executor), amount);\\n\\n try\\n executor.swapAndCompleteBridgeTokens(\\n _transactionId,\\n _swapData,\\n assetId,\\n receiver\\n )\\n {\\n success = true;\\n } catch {\\n token.safeTransfer(refundAddress, amount);\\n }\\n token.safeApprove(address(executor), 0);\\n }\\n\\n if (!success) {\\n emit LiFiTransferRecovered(\\n _transactionId,\\n assetId,\\n refundAddress,\\n amount,\\n block.timestamp\\n );\\n }\\n }\\n\\n /// @notice Sends remaining token to given receiver address (for refund cases)\\n /// @param assetId Address of the token to be withdrawn\\n /// @param receiver Address that will receive tokens\\n /// @param amount Amount of tokens to be withdrawn\\n function withdraw(\\n address assetId,\\n address payable receiver,\\n uint256 amount\\n ) external onlyOwner {\\n if (LibAsset.isNativeAsset(assetId)) {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = receiver.call{ value: amount }(\\\"\\\");\\n if (!success) {\\n revert WithdrawFailed();\\n }\\n } else {\\n IERC20(assetId).safeTransfer(receiver, amount);\\n }\\n emit LogWithdraw(assetId, receiver, amount);\\n }\\n\\n /// @notice Triggers a cBridge refund with calldata produced by cBridge API\\n /// @param _callTo The address to execute the calldata on\\n /// @param _callData The data to execute\\n /// @param _assetAddress Asset to be withdrawn\\n /// @param _to Address to withdraw to\\n /// @param _amount Amount of asset to withdraw\\n function triggerRefund(\\n address payable _callTo,\\n bytes calldata _callData,\\n address _assetAddress,\\n address _to,\\n uint256 _amount\\n ) external onlyOwner {\\n bool success;\\n\\n // make sure that callTo address is either of the cBridge addresses\\n if (\\n cBridgeMessageBus.liquidityBridge() != _callTo &&\\n cBridgeMessageBus.pegBridge() != _callTo &&\\n cBridgeMessageBus.pegBridgeV2() != _callTo &&\\n cBridgeMessageBus.pegVault() != _callTo &&\\n cBridgeMessageBus.pegVaultV2() != _callTo\\n ) {\\n revert ContractCallNotAllowed();\\n }\\n\\n // call contract\\n // solhint-disable-next-line avoid-low-level-calls\\n (success, ) = _callTo.call(_callData);\\n\\n // forward funds to _to address and emit event, if cBridge refund successful\\n if (success) {\\n address sendTo = (LibUtil.isZeroAddress(_to)) ? msg.sender : _to;\\n LibAsset.transferAsset(_assetAddress, payable(sendTo), _amount);\\n emit LogWithdraw(_assetAddress, sendTo, _amount);\\n } else {\\n revert WithdrawFailed();\\n }\\n }\\n\\n // required in order to receive native tokens from cBridge facet\\n // solhint-disable-next-line no-empty-blocks\\n receive() external payable {}\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/interfaces/IBridge.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\ninterface IBridge {\\n function send(\\n address _receiver,\\n address _token,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce,\\n uint32 _maxSlippage\\n ) external;\\n\\n function sendNative(\\n address _receiver,\\n uint256 _amount,\\n uint64 _dstChainId,\\n uint64 _nonce,\\n uint32 _maxSlippage\\n ) external payable;\\n\\n function relay(\\n bytes calldata _relayRequest,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external;\\n\\n function transfers(bytes32 transferId) external view returns (bool);\\n\\n function withdraws(bytes32 withdrawId) external view returns (bool);\\n\\n function withdraw(\\n bytes calldata _wdmsg,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external;\\n\\n /**\\n * @notice Verifies that a message is signed by a quorum among the signers.\\n * @param _msg signed message\\n * @param _sigs list of signatures sorted by signer addresses in ascending order\\n * @param _signers sorted list of current signers\\n * @param _powers powers of current signers\\n */\\n function verifySigs(\\n bytes memory _msg,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external view;\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/interfaces/IOriginalTokenVault.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\ninterface IOriginalTokenVault {\\n /**\\n * @notice Lock original tokens to trigger mint at a remote chain's PeggedTokenBridge\\n * @param _token local token address\\n * @param _amount locked token amount\\n * @param _mintChainId destination chainId to mint tokens\\n * @param _mintAccount destination account to receive minted tokens\\n * @param _nonce user input to guarantee unique depositId\\n */\\n function deposit(\\n address _token,\\n uint256 _amount,\\n uint64 _mintChainId,\\n address _mintAccount,\\n uint64 _nonce\\n ) external;\\n\\n /**\\n * @notice Lock native token as original token to trigger mint at a remote chain's PeggedTokenBridge\\n * @param _amount locked token amount\\n * @param _mintChainId destination chainId to mint tokens\\n * @param _mintAccount destination account to receive minted tokens\\n * @param _nonce user input to guarantee unique depositId\\n */\\n function depositNative(\\n uint256 _amount,\\n uint64 _mintChainId,\\n address _mintAccount,\\n uint64 _nonce\\n ) external payable;\\n\\n /**\\n * @notice Withdraw locked original tokens triggered by a burn at a remote chain's PeggedTokenBridge.\\n * @param _request The serialized Withdraw protobuf.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the bridge's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function withdraw(\\n bytes calldata _request,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external;\\n\\n function records(bytes32 recordId) external view returns (bool);\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/interfaces/IOriginalTokenVaultV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\ninterface IOriginalTokenVaultV2 {\\n /**\\n * @notice Lock original tokens to trigger mint at a remote chain's PeggedTokenBridge\\n * @param _token local token address\\n * @param _amount locked token amount\\n * @param _mintChainId destination chainId to mint tokens\\n * @param _mintAccount destination account to receive minted tokens\\n * @param _nonce user input to guarantee unique depositId\\n */\\n function deposit(\\n address _token,\\n uint256 _amount,\\n uint64 _mintChainId,\\n address _mintAccount,\\n uint64 _nonce\\n ) external returns (bytes32);\\n\\n /**\\n * @notice Lock native token as original token to trigger mint at a remote chain's PeggedTokenBridge\\n * @param _amount locked token amount\\n * @param _mintChainId destination chainId to mint tokens\\n * @param _mintAccount destination account to receive minted tokens\\n * @param _nonce user input to guarantee unique depositId\\n */\\n function depositNative(\\n uint256 _amount,\\n uint64 _mintChainId,\\n address _mintAccount,\\n uint64 _nonce\\n ) external payable returns (bytes32);\\n\\n /**\\n * @notice Withdraw locked original tokens triggered by a burn at a remote chain's PeggedTokenBridge.\\n * @param _request The serialized Withdraw protobuf.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the bridge's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function withdraw(\\n bytes calldata _request,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external returns (bytes32);\\n\\n function records(bytes32 recordId) external view returns (bool);\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/interfaces/IPeggedTokenBridge.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\ninterface IPeggedTokenBridge {\\n /**\\n * @notice Burn tokens to trigger withdrawal at a remote chain's OriginalTokenVault\\n * @param _token local token address\\n * @param _amount locked token amount\\n * @param _withdrawAccount account who withdraw original tokens on the remote chain\\n * @param _nonce user input to guarantee unique depositId\\n */\\n function burn(\\n address _token,\\n uint256 _amount,\\n address _withdrawAccount,\\n uint64 _nonce\\n ) external;\\n\\n /**\\n * @notice Mint tokens triggered by deposit at a remote chain's OriginalTokenVault.\\n * @param _request The serialized Mint protobuf.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the sigsVerifier's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function mint(\\n bytes calldata _request,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external;\\n\\n function records(bytes32 recordId) external view returns (bool);\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/interfaces/IPeggedTokenBridgeV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\ninterface IPeggedTokenBridgeV2 {\\n /**\\n * @notice Burn pegged tokens to trigger a cross-chain withdrawal of the original tokens at a remote chain's\\n * OriginalTokenVault, or mint at another remote chain\\n * @param _token The pegged token address.\\n * @param _amount The amount to burn.\\n * @param _toChainId If zero, withdraw from original vault; otherwise, the remote chain to mint tokens.\\n * @param _toAccount The account to receive tokens on the remote chain\\n * @param _nonce A number to guarantee unique depositId. Can be timestamp in practice.\\n */\\n function burn(\\n address _token,\\n uint256 _amount,\\n uint64 _toChainId,\\n address _toAccount,\\n uint64 _nonce\\n ) external returns (bytes32);\\n\\n // same with `burn` above, use openzeppelin ERC20Burnable interface\\n function burnFrom(\\n address _token,\\n uint256 _amount,\\n uint64 _toChainId,\\n address _toAccount,\\n uint64 _nonce\\n ) external returns (bytes32);\\n\\n /**\\n * @notice Mint tokens triggered by deposit at a remote chain's OriginalTokenVault.\\n * @param _request The serialized Mint protobuf.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the sigsVerifier's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function mint(\\n bytes calldata _request,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external returns (bytes32);\\n\\n function records(bytes32 recordId) external view returns (bool);\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/message/interfaces/IMessageBus.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\nimport \\\"../libraries/MsgDataTypes.sol\\\";\\n\\ninterface IMessageBus {\\n /**\\n * @notice Send a message to a contract on another chain.\\n * Sender needs to make sure the uniqueness of the message Id, which is computed as\\n * hash(type.MessageOnly, sender, receiver, srcChainId, srcTxHash, dstChainId, message).\\n * If messages with the same Id are sent, only one of them will succeed at dst chain..\\n * A fee is charged in the native gas token.\\n * @param _receiver The address of the destination app contract.\\n * @param _dstChainId The destination chain ID.\\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\\n */\\n function sendMessage(\\n address _receiver,\\n uint256 _dstChainId,\\n bytes calldata _message\\n ) external payable;\\n\\n // same as above, except that receiver is an non-evm chain address,\\n function sendMessage(\\n bytes calldata _receiver,\\n uint256 _dstChainId,\\n bytes calldata _message\\n ) external payable;\\n\\n /**\\n * @notice Send a message associated with a token transfer to a contract on another chain.\\n * If messages with the same srcTransferId are sent, only one of them will succeed at dst chain..\\n * A fee is charged in the native token.\\n * @param _receiver The address of the destination app contract.\\n * @param _dstChainId The destination chain ID.\\n * @param _srcBridge The bridge contract to send the transfer with.\\n * @param _srcTransferId The transfer ID.\\n * @param _dstChainId The destination chain ID.\\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\\n */\\n function sendMessageWithTransfer(\\n address _receiver,\\n uint256 _dstChainId,\\n address _srcBridge,\\n bytes32 _srcTransferId,\\n bytes calldata _message\\n ) external payable;\\n\\n /**\\n * @notice Execute a message not associated with a transfer.\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the sigsVerifier's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function executeMessage(\\n bytes calldata _message,\\n MsgDataTypes.RouteInfo calldata _route,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external payable;\\n\\n /**\\n * @notice Execute a message with a successful transfer.\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param _transfer The transfer info.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the sigsVerifier's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function executeMessageWithTransfer(\\n bytes calldata _message,\\n MsgDataTypes.TransferInfo calldata _transfer,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external payable;\\n\\n /**\\n * @notice Execute a message with a refunded transfer.\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param _transfer The transfer info.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\\n * +2/3 of the sigsVerifier's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function executeMessageWithTransferRefund(\\n bytes calldata _message, // the same message associated with the original transfer\\n MsgDataTypes.TransferInfo calldata _transfer,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external payable;\\n\\n /**\\n * @notice Withdraws message fee in the form of native gas token.\\n * @param _account The address receiving the fee.\\n * @param _cumulativeFee The cumulative fee credited to the account. Tracked by SGN.\\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A withdrawal must be\\n * signed-off by +2/3 of the sigsVerifier's current signing power to be delivered.\\n * @param _signers The sorted list of signers.\\n * @param _powers The signing powers of the signers.\\n */\\n function withdrawFee(\\n address _account,\\n uint256 _cumulativeFee,\\n bytes[] calldata _sigs,\\n address[] calldata _signers,\\n uint256[] calldata _powers\\n ) external;\\n\\n /**\\n * @notice Calculates the required fee for the message.\\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\\n @ @return The required fee.\\n */\\n function calcFee(bytes calldata _message) external view returns (uint256);\\n\\n function liquidityBridge() external view returns (address);\\n\\n function pegBridge() external view returns (address);\\n\\n function pegBridgeV2() external view returns (address);\\n\\n function pegVault() external view returns (address);\\n\\n function pegVaultV2() external view returns (address);\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/message/libraries/MsgDataTypes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\nlibrary MsgDataTypes {\\n string constant ABORT_PREFIX = \\\"MSG::ABORT:\\\";\\n\\n // bridge operation type at the sender side (src chain)\\n enum BridgeSendType {\\n Null,\\n Liquidity,\\n PegDeposit,\\n PegBurn,\\n PegV2Deposit,\\n PegV2Burn,\\n PegV2BurnFrom\\n }\\n\\n // bridge operation type at the receiver side (dst chain)\\n enum TransferType {\\n Null,\\n LqRelay, // relay through liquidity bridge\\n LqWithdraw, // withdraw from liquidity bridge\\n PegMint, // mint through pegged token bridge\\n PegWithdraw, // withdraw from original token vault\\n PegV2Mint, // mint through pegged token bridge v2\\n PegV2Withdraw // withdraw from original token vault v2\\n }\\n\\n enum MsgType {\\n MessageWithTransfer,\\n MessageOnly\\n }\\n\\n enum TxStatus {\\n Null,\\n Success,\\n Fail,\\n Fallback,\\n Pending // transient state within a transaction\\n }\\n\\n struct TransferInfo {\\n TransferType t;\\n address sender;\\n address receiver;\\n address token;\\n uint256 amount;\\n uint64 wdseq; // only needed for LqWithdraw (refund)\\n uint64 srcChainId;\\n bytes32 refId;\\n bytes32 srcTxHash; // src chain msg tx hash\\n }\\n\\n struct RouteInfo {\\n address sender;\\n address receiver;\\n uint64 srcChainId;\\n bytes32 srcTxHash; // src chain msg tx hash\\n }\\n\\n // used for msg from non-evm chains with longer-bytes address\\n struct RouteInfo2 {\\n bytes sender;\\n address receiver;\\n uint64 srcChainId;\\n bytes32 srcTxHash;\\n }\\n\\n // combination of RouteInfo and RouteInfo2 for easier processing\\n struct Route {\\n address sender; // from RouteInfo\\n bytes senderBytes; // from RouteInfo2\\n address receiver;\\n uint64 srcChainId;\\n bytes32 srcTxHash;\\n }\\n\\n struct MsgWithTransferExecutionParams {\\n bytes message;\\n TransferInfo transfer;\\n bytes[] sigs;\\n address[] signers;\\n uint256[] powers;\\n }\\n\\n struct BridgeTransferParams {\\n bytes request;\\n bytes[] sigs;\\n address[] signers;\\n uint256[] powers;\\n }\\n}\\n\"\r\n },\r\n \"src/Facets/PeripheryRegistryFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\n\\n/// @title Periphery Registry Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice A simple registry to track LIFI periphery contracts\\n/// @custom:version 1.0.0\\ncontract PeripheryRegistryFacet {\\n /// Storage ///\\n\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.facets.periphery_registry\\\");\\n\\n /// Types ///\\n\\n struct Storage {\\n mapping(string => address) contracts;\\n }\\n\\n /// Events ///\\n\\n event PeripheryContractRegistered(string name, address contractAddress);\\n\\n /// External Methods ///\\n\\n /// @notice Registers a periphery contract address with a specified name\\n /// @param _name the name to register the contract address under\\n /// @param _contractAddress the address of the contract to register\\n function registerPeripheryContract(\\n string calldata _name,\\n address _contractAddress\\n ) external {\\n LibDiamond.enforceIsContractOwner();\\n Storage storage s = getStorage();\\n s.contracts[_name] = _contractAddress;\\n emit PeripheryContractRegistered(_name, _contractAddress);\\n }\\n\\n /// @notice Returns the registered contract address by its name\\n /// @param _name the registered name of the contract\\n function getPeripheryContract(\\n string calldata _name\\n ) external view returns (address) {\\n return getStorage().contracts[_name];\\n }\\n\\n /// @dev fetch local storage\\n function getStorage() private pure returns (Storage storage s) {\\n bytes32 namespace = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n s.slot := namespace\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IExecutor.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\n/// @title Interface for Executor\\n/// @author LI.FI (https://li.fi)\\ninterface IExecutor {\\n /// @notice Performs a swap before completing a cross-chain transaction\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swapData array of data needed for swaps\\n /// @param transferredAssetId token received from the other chain\\n /// @param receiver address that will receive tokens in the end\\n function swapAndCompleteBridgeTokens(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swapData,\\n address transferredAssetId,\\n address payable receiver\\n ) external payable;\\n}\\n\"\r\n },\r\n \"src/Helpers/TransferrableOwnership.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IERC173 } from \\\"../Interfaces/IERC173.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\n\\ncontract TransferrableOwnership is IERC173 {\\n address public owner;\\n address public pendingOwner;\\n\\n /// Errors ///\\n error UnAuthorized();\\n error NoNullOwner();\\n error NewOwnerMustNotBeSelf();\\n error NoPendingOwnershipTransfer();\\n error NotPendingOwner();\\n\\n /// Events ///\\n event OwnershipTransferRequested(\\n address indexed _from,\\n address indexed _to\\n );\\n\\n constructor(address initialOwner) {\\n owner = initialOwner;\\n }\\n\\n modifier onlyOwner() {\\n if (msg.sender != owner) revert UnAuthorized();\\n _;\\n }\\n\\n /// @notice Initiates transfer of ownership to a new address\\n /// @param _newOwner the address to transfer ownership to\\n function transferOwnership(address _newOwner) external onlyOwner {\\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\\n pendingOwner = _newOwner;\\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\\n }\\n\\n /// @notice Cancel transfer of ownership\\n function cancelOwnershipTransfer() external onlyOwner {\\n if (pendingOwner == LibAsset.NULL_ADDRESS)\\n revert NoPendingOwnershipTransfer();\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n\\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\\n function confirmOwnershipTransfer() external {\\n address _pendingOwner = pendingOwner;\\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\\n emit OwnershipTransferred(owner, _pendingOwner);\\n owner = _pendingOwner;\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n}\\n\"\r\n },\r\n \"lib/sgn-v2-contracts/contracts/message/interfaces/IMessageReceiverApp.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: GPL-3.0-only\\n\\npragma solidity >=0.8.0;\\n\\ninterface IMessageReceiverApp {\\n enum ExecutionStatus {\\n Fail, // execution failed, finalized\\n Success, // execution succeeded, finalized\\n Retry // execution rejected, can retry later\\n }\\n\\n /**\\n * @notice Called by MessageBus to execute a message\\n * @param _sender The address of the source app contract\\n * @param _srcChainId The source chain ID where the transfer is originated from\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param _executor Address who called the MessageBus execution function\\n */\\n function executeMessage(\\n address _sender,\\n uint64 _srcChainId,\\n bytes calldata _message,\\n address _executor\\n ) external payable returns (ExecutionStatus);\\n\\n // same as above, except that sender is an non-evm chain address,\\n // otherwise same as above.\\n function executeMessage(\\n bytes calldata _sender,\\n uint64 _srcChainId,\\n bytes calldata _message,\\n address _executor\\n ) external payable returns (ExecutionStatus);\\n\\n /**\\n * @notice Called by MessageBus to execute a message with an associated token transfer.\\n * The contract is guaranteed to have received the right amount of tokens before this function is called.\\n * @param _sender The address of the source app contract\\n * @param _token The address of the token that comes out of the bridge\\n * @param _amount The amount of tokens received at this contract through the cross-chain bridge.\\n * @param _srcChainId The source chain ID where the transfer is originated from\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param _executor Address who called the MessageBus execution function\\n */\\n function executeMessageWithTransfer(\\n address _sender,\\n address _token,\\n uint256 _amount,\\n uint64 _srcChainId,\\n bytes calldata _message,\\n address _executor\\n ) external payable returns (ExecutionStatus);\\n\\n /**\\n * @notice Only called by MessageBus if\\n * 1. executeMessageWithTransfer reverts, or\\n * 2. executeMessageWithTransfer returns ExecutionStatus.Fail\\n * The contract is guaranteed to have received the right amount of tokens before this function is called.\\n * @param _sender The address of the source app contract\\n * @param _token The address of the token that comes out of the bridge\\n * @param _amount The amount of tokens received at this contract through the cross-chain bridge.\\n * @param _srcChainId The source chain ID where the transfer is originated from\\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\\n * @param _executor Address who called the MessageBus execution function\\n */\\n function executeMessageWithTransferFallback(\\n address _sender,\\n address _token,\\n uint256 _amount,\\n uint64 _srcChainId,\\n bytes calldata _message,\\n address _executor\\n ) external payable returns (ExecutionStatus);\\n\\n /**\\n * @notice Called by MessageBus to process refund of the original transfer from this contract.\\n * The contract is guaranteed to have received the refund before this function is called.\\n * @param _token The token address of the original transfer\\n * @param _amount The amount of the original transfer\\n * @param _message The same message associated with the original transfer\\n * @param _executor Address who called the MessageBus execution function\\n */\\n function executeMessageWithTransferRefund(\\n address _token,\\n uint256 _amount,\\n bytes calldata _message,\\n address _executor\\n ) external payable returns (ExecutionStatus);\\n}\\n\"\r\n },\r\n \"src/Interfaces/IERC173.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\n/// @title ERC-173 Contract Ownership Standard\\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\\n/* is ERC165 */\\ninterface IERC173 {\\n /// @dev This emits when ownership of a contract changes.\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n /// @notice Get the address of the owner\\n /// @return owner_ The address of the owner.\\n function owner() external view returns (address owner_);\\n\\n /// @notice Set the address of the new owner of the contract\\n /// @dev Set _newOwner to address(0) to renounce any ownership.\\n /// @param _newOwner The address of the new owner of the contract\\n function transferOwnership(address _newOwner) external;\\n}\\n\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"extractBridgeData\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"extractData\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"swapData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"extractGenericSwapParameters\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"receivingAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"extractMainParameters\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"extractSwapData\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"swapData\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"name\":\"validateCalldata\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callTo\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"dstCalldata\",\"type\":\"bytes\"}],\"name\":\"validateDestinationCalldata\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isValid\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + ContractName: "CalldataVerificationFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/CalldataVerificationFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { AmarokFacet } from \"./AmarokFacet.sol\";\nimport { StargateFacet } from \"./StargateFacet.sol\";\nimport { CelerIMFacetBase, CelerIM } from \"lifi/Helpers/CelerIMFacetBase.sol\";\nimport { StandardizedCallFacet } from \"lifi/Facets/StandardizedCallFacet.sol\";\nimport { LibBytes } from \"../Libraries/LibBytes.sol\";\n\n/// @title Calldata Verification Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for verifying calldata\n/// @custom:version 1.1.1\ncontract CalldataVerificationFacet {\n using LibBytes for bytes;\n\n /// @notice Extracts the bridge data from the calldata\n /// @param data The calldata to extract the bridge data from\n /// @return bridgeData The bridge data extracted from the calldata\n function extractBridgeData(\n bytes calldata data\n ) external pure returns (ILiFi.BridgeData memory bridgeData) {\n bridgeData = _extractBridgeData(data);\n }\n\n /// @notice Extracts the swap data from the calldata\n /// @param data The calldata to extract the swap data from\n /// @return swapData The swap data extracted from the calldata\n function extractSwapData(\n bytes calldata data\n ) external pure returns (LibSwap.SwapData[] memory swapData) {\n swapData = _extractSwapData(data);\n }\n\n /// @notice Extracts the bridge data and swap data from the calldata\n /// @param data The calldata to extract the bridge data and swap data from\n /// @return bridgeData The bridge data extracted from the calldata\n /// @return swapData The swap data extracted from the calldata\n function extractData(\n bytes calldata data\n )\n external\n pure\n returns (\n ILiFi.BridgeData memory bridgeData,\n LibSwap.SwapData[] memory swapData\n )\n {\n bridgeData = _extractBridgeData(data);\n if (bridgeData.hasSourceSwaps) {\n swapData = _extractSwapData(data);\n }\n }\n\n /// @notice Extracts the main parameters from the calldata\n /// @param data The calldata to extract the main parameters from\n /// @return bridge The bridge extracted from the calldata\n /// @return sendingAssetId The sending asset id extracted from the calldata\n /// @return receiver The receiver extracted from the calldata\n /// @return amount The min amountfrom the calldata\n /// @return destinationChainId The destination chain id extracted from the calldata\n /// @return hasSourceSwaps Whether the calldata has source swaps\n /// @return hasDestinationCall Whether the calldata has a destination call\n function extractMainParameters(\n bytes calldata data\n )\n public\n pure\n returns (\n string memory bridge,\n address sendingAssetId,\n address receiver,\n uint256 amount,\n uint256 destinationChainId,\n bool hasSourceSwaps,\n bool hasDestinationCall\n )\n {\n ILiFi.BridgeData memory bridgeData = _extractBridgeData(data);\n\n if (bridgeData.hasSourceSwaps) {\n LibSwap.SwapData[] memory swapData = _extractSwapData(data);\n sendingAssetId = swapData[0].sendingAssetId;\n amount = swapData[0].fromAmount;\n } else {\n sendingAssetId = bridgeData.sendingAssetId;\n amount = bridgeData.minAmount;\n }\n\n return (\n bridgeData.bridge,\n sendingAssetId,\n bridgeData.receiver,\n amount,\n bridgeData.destinationChainId,\n bridgeData.hasSourceSwaps,\n bridgeData.hasDestinationCall\n );\n }\n\n /// @notice Extracts the generic swap parameters from the calldata\n /// @param data The calldata to extract the generic swap parameters from\n /// @return sendingAssetId The sending asset id extracted from the calldata\n /// @return amount The amount extracted from the calldata\n /// @return receiver The receiver extracted from the calldata\n /// @return receivingAssetId The receiving asset id extracted from the calldata\n /// @return receivingAmount The receiving amount extracted from the calldata\n function extractGenericSwapParameters(\n bytes calldata data\n )\n public\n pure\n returns (\n address sendingAssetId,\n uint256 amount,\n address receiver,\n address receivingAssetId,\n uint256 receivingAmount\n )\n {\n LibSwap.SwapData[] memory swapData;\n bytes memory callData = data;\n\n if (\n bytes4(data[:4]) == StandardizedCallFacet.standardizedCall.selector\n ) {\n // standardizedCall\n callData = abi.decode(data[4:], (bytes));\n }\n (, , , receiver, receivingAmount, swapData) = abi.decode(\n callData.slice(4, callData.length - 4),\n (bytes32, string, string, address, uint256, LibSwap.SwapData[])\n );\n\n sendingAssetId = swapData[0].sendingAssetId;\n amount = swapData[0].fromAmount;\n receivingAssetId = swapData[swapData.length - 1].receivingAssetId;\n return (\n sendingAssetId,\n amount,\n receiver,\n receivingAssetId,\n receivingAmount\n );\n }\n\n /// @notice Validates the calldata\n /// @param data The calldata to validate\n /// @param bridge The bridge to validate or empty string to ignore\n /// @param sendingAssetId The sending asset id to validate\n /// or 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF to ignore\n /// @param receiver The receiver to validate\n /// or 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF to ignore\n /// @param amount The amount to validate or type(uint256).max to ignore\n /// @param destinationChainId The destination chain id to validate\n /// or type(uint256).max to ignore\n /// @param hasSourceSwaps Whether the calldata has source swaps\n /// @param hasDestinationCall Whether the calldata has a destination call\n /// @return isValid Whether the calldata is validate\n function validateCalldata(\n bytes calldata data,\n string calldata bridge,\n address sendingAssetId,\n address receiver,\n uint256 amount,\n uint256 destinationChainId,\n bool hasSourceSwaps,\n bool hasDestinationCall\n ) external pure returns (bool isValid) {\n ILiFi.BridgeData memory bridgeData;\n (\n bridgeData.bridge,\n bridgeData.sendingAssetId,\n bridgeData.receiver,\n bridgeData.minAmount,\n bridgeData.destinationChainId,\n bridgeData.hasSourceSwaps,\n bridgeData.hasDestinationCall\n ) = extractMainParameters(data);\n return\n // Check bridge\n (keccak256(abi.encodePacked(bridge)) ==\n keccak256(abi.encodePacked(\"\")) ||\n keccak256(abi.encodePacked(bridgeData.bridge)) ==\n keccak256(abi.encodePacked(bridge))) &&\n // Check sendingAssetId\n (sendingAssetId == 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF ||\n bridgeData.sendingAssetId == sendingAssetId) &&\n // Check receiver\n (receiver == 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF ||\n bridgeData.receiver == receiver) &&\n // Check amount\n (amount == type(uint256).max || bridgeData.minAmount == amount) &&\n // Check destinationChainId\n (destinationChainId == type(uint256).max ||\n bridgeData.destinationChainId == destinationChainId) &&\n // Check hasSourceSwaps\n bridgeData.hasSourceSwaps == hasSourceSwaps &&\n // Check hasDestinationCall\n bridgeData.hasDestinationCall == hasDestinationCall;\n }\n\n /// @notice Validates the destination calldata\n /// @param data The calldata to validate\n /// @param callTo The call to address to validate\n /// @param dstCalldata The destination calldata to validate\n /// @return isValid Whether the destination calldata is validate\n function validateDestinationCalldata(\n bytes calldata data,\n bytes calldata callTo,\n bytes calldata dstCalldata\n ) external pure returns (bool isValid) {\n bytes memory callData = data;\n\n // Handle standardizedCall\n if (\n bytes4(data[:4]) == StandardizedCallFacet.standardizedCall.selector\n ) {\n callData = abi.decode(data[4:], (bytes));\n }\n\n bytes4 selector = abi.decode(callData, (bytes4));\n\n // Case: Amarok\n if (selector == AmarokFacet.startBridgeTokensViaAmarok.selector) {\n (, AmarokFacet.AmarokData memory amarokData) = abi.decode(\n callData.slice(4, callData.length - 4),\n (ILiFi.BridgeData, AmarokFacet.AmarokData)\n );\n\n return\n keccak256(dstCalldata) == keccak256(amarokData.callData) &&\n abi.decode(callTo, (address)) == amarokData.callTo;\n }\n if (\n selector == AmarokFacet.swapAndStartBridgeTokensViaAmarok.selector\n ) {\n (, , AmarokFacet.AmarokData memory amarokData) = abi.decode(\n callData.slice(4, callData.length - 4),\n (ILiFi.BridgeData, LibSwap.SwapData[], AmarokFacet.AmarokData)\n );\n return\n keccak256(dstCalldata) == keccak256(amarokData.callData) &&\n abi.decode(callTo, (address)) == amarokData.callTo;\n }\n\n // Case: Stargate\n if (selector == StargateFacet.startBridgeTokensViaStargate.selector) {\n (, StargateFacet.StargateData memory stargateData) = abi.decode(\n callData.slice(4, callData.length - 4),\n (ILiFi.BridgeData, StargateFacet.StargateData)\n );\n return\n keccak256(dstCalldata) == keccak256(stargateData.callData) &&\n keccak256(callTo) == keccak256(stargateData.callTo);\n }\n if (\n selector ==\n StargateFacet.swapAndStartBridgeTokensViaStargate.selector\n ) {\n (, , StargateFacet.StargateData memory stargateData) = abi.decode(\n callData.slice(4, callData.length - 4),\n (\n ILiFi.BridgeData,\n LibSwap.SwapData[],\n StargateFacet.StargateData\n )\n );\n return\n keccak256(dstCalldata) == keccak256(stargateData.callData) &&\n keccak256(callTo) == keccak256(stargateData.callTo);\n }\n // Case: Celer\n if (\n selector == CelerIMFacetBase.startBridgeTokensViaCelerIM.selector\n ) {\n (, CelerIM.CelerIMData memory celerIMData) = abi.decode(\n callData.slice(4, callData.length - 4),\n (ILiFi.BridgeData, CelerIM.CelerIMData)\n );\n return\n keccak256(dstCalldata) == keccak256(celerIMData.callData) &&\n keccak256(callTo) == keccak256(celerIMData.callTo);\n }\n if (\n selector ==\n CelerIMFacetBase.swapAndStartBridgeTokensViaCelerIM.selector\n ) {\n (, , CelerIM.CelerIMData memory celerIMData) = abi.decode(\n callData.slice(4, callData.length - 4),\n (ILiFi.BridgeData, LibSwap.SwapData[], CelerIM.CelerIMData)\n );\n return\n keccak256(dstCalldata) == keccak256(celerIMData.callData) &&\n keccak256(callTo) == keccak256(celerIMData.callTo);\n }\n\n // All other cases\n return false;\n }\n\n /// Internal Methods ///\n\n /// @notice Extracts the bridge data from the calldata\n /// @param data The calldata to extract the bridge data from\n /// @return bridgeData The bridge data extracted from the calldata\n function _extractBridgeData(\n bytes calldata data\n ) internal pure returns (ILiFi.BridgeData memory bridgeData) {\n if (\n bytes4(data[:4]) == StandardizedCallFacet.standardizedCall.selector\n ) {\n // StandardizedCall\n bytes memory unwrappedData = abi.decode(data[4:], (bytes));\n bridgeData = abi.decode(\n unwrappedData.slice(4, unwrappedData.length - 4),\n (ILiFi.BridgeData)\n );\n return bridgeData;\n }\n // normal call\n bridgeData = abi.decode(data[4:], (ILiFi.BridgeData));\n }\n\n /// @notice Extracts the swap data from the calldata\n /// @param data The calldata to extract the swap data from\n /// @return swapData The swap data extracted from the calldata\n function _extractSwapData(\n bytes calldata data\n ) internal pure returns (LibSwap.SwapData[] memory swapData) {\n if (\n bytes4(data[:4]) == StandardizedCallFacet.standardizedCall.selector\n ) {\n // standardizedCall\n bytes memory unwrappedData = abi.decode(data[4:], (bytes));\n (, swapData) = abi.decode(\n unwrappedData.slice(4, unwrappedData.length - 4),\n (ILiFi.BridgeData, LibSwap.SwapData[])\n );\n return swapData;\n }\n // normal call\n (, swapData) = abi.decode(\n data[4:],\n (ILiFi.BridgeData, LibSwap.SwapData[])\n );\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Facets/AmarokFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IConnextHandler } from \"../Interfaces/IConnextHandler.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { InformationMismatch } from \"../Errors/GenericErrors.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title Amarok Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Connext Amarok\n/// @custom:version 2.0.0\ncontract AmarokFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n /// @notice The contract address of the connext handler on the source chain.\n IConnextHandler private immutable connextHandler;\n\n /// @param callData The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.\n /// @param callTo The address of the contract on dest chain that will receive bridged funds and execute data\n /// @param relayerFee The amount of relayer fee the tx called xcall with\n /// @param slippageTol Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)\n /// @param delegate Destination delegate address\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\n /// @param payFeeWithSendingAsset Whether to pay the relayer fee with the sending asset or not\n struct AmarokData {\n bytes callData;\n address callTo;\n uint256 relayerFee;\n uint256 slippageTol;\n address delegate;\n uint32 destChainDomainId;\n bool payFeeWithSendingAsset;\n }\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _connextHandler The contract address of the connext handler on the source chain.\n constructor(IConnextHandler _connextHandler) {\n connextHandler = _connextHandler;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Amarok\n /// @param _bridgeData Data containing core information for bridging\n /// @param _amarokData Data specific to bridge\n function startBridgeTokensViaAmarok(\n BridgeData calldata _bridgeData,\n AmarokData calldata _amarokData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n noNativeAsset(_bridgeData)\n {\n validateDestinationCallFlag(_bridgeData, _amarokData);\n\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n\n _startBridge(_bridgeData, _amarokData);\n }\n\n /// @notice Performs a swap before bridging via Amarok\n /// @param _bridgeData The core information needed for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _amarokData Data specific to Amarok\n function swapAndStartBridgeTokensViaAmarok(\n BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n AmarokData calldata _amarokData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n noNativeAsset(_bridgeData)\n {\n validateDestinationCallFlag(_bridgeData, _amarokData);\n\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n _amarokData.relayerFee\n );\n\n _startBridge(_bridgeData, _amarokData);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via Amarok\n /// @param _bridgeData The core information needed for bridging\n /// @param _amarokData Data specific to Amarok\n function _startBridge(\n BridgeData memory _bridgeData,\n AmarokData calldata _amarokData\n ) private {\n // give max approval for token to Amarok bridge, if not already\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(connextHandler),\n _bridgeData.minAmount\n );\n\n // initiate bridge transaction\n if (_amarokData.payFeeWithSendingAsset) {\n connextHandler.xcall(\n _amarokData.destChainDomainId,\n _amarokData.callTo,\n _bridgeData.sendingAssetId,\n _amarokData.delegate,\n _bridgeData.minAmount - _amarokData.relayerFee,\n _amarokData.slippageTol,\n _amarokData.callData,\n _amarokData.relayerFee\n );\n } else {\n connextHandler.xcall{ value: _amarokData.relayerFee }(\n _amarokData.destChainDomainId,\n _amarokData.callTo,\n _bridgeData.sendingAssetId,\n _amarokData.delegate,\n _bridgeData.minAmount,\n _amarokData.slippageTol,\n _amarokData.callData\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n function validateDestinationCallFlag(\n ILiFi.BridgeData memory _bridgeData,\n AmarokData calldata _amarokData\n ) private pure {\n if (\n (_amarokData.callData.length > 0) != _bridgeData.hasDestinationCall\n ) {\n revert InformationMismatch();\n }\n }\n}\n" + }, + "src/Facets/StargateFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IStargateRouter } from \"../Interfaces/IStargateRouter.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { InformationMismatch, AlreadyInitialized, NotInitialized } from \"../Errors/GenericErrors.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title Stargate Facet\n/// @author Li.Finance (https://li.finance)\n/// @notice Provides functionality for bridging through Stargate\n/// @custom:version 2.1.0\ncontract StargateFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// CONSTANTS ///\n\n /// @notice The contract address of the stargate router on the source chain.\n IStargateRouter private immutable router;\n /// @notice The contract address of the native stargate router on the source chain.\n IStargateRouter private immutable nativeRouter;\n /// @notice The contract address of the stargate composer on the source chain.\n IStargateRouter private immutable composer;\n\n /// Storage ///\n\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.facets.stargate\");\n\n /// Types ///\n\n struct Storage {\n mapping(uint256 => uint16) layerZeroChainId;\n bool initialized;\n }\n\n struct ChainIdConfig {\n uint256 chainId;\n uint16 layerZeroChainId;\n }\n\n /// @param srcPoolId Source pool id.\n /// @param dstPoolId Dest pool id.\n /// @param minAmountLD The min qty you would accept on the destination.\n /// @param dstGasForCall Additional gas fee for extral call on the destination.\n /// @param lzFee Estimated message fee.\n /// @param refundAddress Refund adddress. Extra gas (if any) is returned to this address\n /// @param callTo The address to send the tokens to on the destination.\n /// @param callData Additional payload.\n struct StargateData {\n uint256 srcPoolId;\n uint256 dstPoolId;\n uint256 minAmountLD;\n uint256 dstGasForCall;\n uint256 lzFee;\n address payable refundAddress;\n bytes callTo;\n bytes callData;\n }\n\n /// Errors ///\n\n error UnknownLayerZeroChain();\n\n /// Events ///\n\n event StargateInitialized(ChainIdConfig[] chainIdConfigs);\n\n event LayerZeroChainIdSet(\n uint256 indexed chainId,\n uint16 layerZeroChainId\n );\n\n /// @notice Emit to get credited for referral\n /// @dev Our partner id is 0x0006\n event PartnerSwap(bytes2 partnerId);\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _router The contract address of the stargate router on the source chain.\n /// @param _nativeRouter The contract address of the native token stargate router on the source chain.\n constructor(\n IStargateRouter _router,\n IStargateRouter _nativeRouter,\n IStargateRouter _composer\n ) {\n router = _router;\n nativeRouter = _nativeRouter;\n composer = _composer;\n }\n\n /// Init ///\n\n /// @notice Initialize local variables for the Stargate Facet\n /// @param chainIdConfigs Chain Id configuration data\n function initStargate(ChainIdConfig[] calldata chainIdConfigs) external {\n LibDiamond.enforceIsContractOwner();\n\n Storage storage sm = getStorage();\n\n for (uint256 i = 0; i < chainIdConfigs.length; i++) {\n sm.layerZeroChainId[chainIdConfigs[i].chainId] = chainIdConfigs[i]\n .layerZeroChainId;\n }\n\n sm.initialized = true;\n\n emit StargateInitialized(chainIdConfigs);\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Stargate Bridge\n /// @param _bridgeData Data used purely for tracking and analytics\n /// @param _stargateData Data specific to Stargate Bridge\n function startBridgeTokensViaStargate(\n ILiFi.BridgeData calldata _bridgeData,\n StargateData calldata _stargateData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n validateDestinationCallFlag(_bridgeData, _stargateData);\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData, _stargateData);\n }\n\n /// @notice Performs a swap before bridging via Stargate Bridge\n /// @param _bridgeData Data used purely for tracking and analytics\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _stargateData Data specific to Stargate Bridge\n function swapAndStartBridgeTokensViaStargate(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n StargateData calldata _stargateData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n validateDestinationCallFlag(_bridgeData, _stargateData);\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n LibAsset.isNativeAsset(_bridgeData.sendingAssetId)\n ? 0\n : _stargateData.lzFee\n );\n\n _startBridge(_bridgeData, _stargateData);\n }\n\n function quoteLayerZeroFee(\n uint256 _destinationChainId,\n StargateData calldata _stargateData\n ) external view returns (uint256, uint256) {\n // Transfers with callData have to be routed via the composer which adds additional overhead in fees.\n // The composer exposes the same function as the router to calculate those fees.\n IStargateRouter stargate = _stargateData.callData.length > 0\n ? composer\n : router;\n return\n stargate.quoteLayerZeroFee(\n getLayerZeroChainId(_destinationChainId),\n 1, // TYPE_SWAP_REMOTE on Bridge\n _stargateData.callTo,\n _stargateData.callData,\n IStargateRouter.lzTxObj(\n _stargateData.dstGasForCall,\n 0,\n toBytes(address(0))\n )\n );\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via Stargate Bridge\n /// @param _bridgeData Data used purely for tracking and analytics\n /// @param _stargateData Data specific to Stargate Bridge\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n StargateData calldata _stargateData\n ) private {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // All transfers with destination calls need to be routed via the composer contract\n IStargateRouter stargate = _bridgeData.hasDestinationCall\n ? composer\n : nativeRouter;\n\n stargate.swapETHAndCall{ value: _bridgeData.minAmount }(\n getLayerZeroChainId(_bridgeData.destinationChainId),\n _stargateData.refundAddress,\n _stargateData.callTo,\n IStargateRouter.SwapAmount(\n _bridgeData.minAmount - _stargateData.lzFee,\n _stargateData.minAmountLD\n ),\n IStargateRouter.lzTxObj(\n _stargateData.dstGasForCall,\n 0,\n toBytes(address(0))\n ),\n _stargateData.callData\n );\n } else {\n // All transfers with destination calls need to be routed via the composer contract\n IStargateRouter stargate = _bridgeData.hasDestinationCall\n ? composer\n : router;\n\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(stargate),\n _bridgeData.minAmount\n );\n\n stargate.swap{ value: _stargateData.lzFee }(\n getLayerZeroChainId(_bridgeData.destinationChainId),\n _stargateData.srcPoolId,\n _stargateData.dstPoolId,\n _stargateData.refundAddress,\n _bridgeData.minAmount,\n _stargateData.minAmountLD,\n IStargateRouter.lzTxObj(\n _stargateData.dstGasForCall,\n 0,\n toBytes(address(0))\n ),\n _stargateData.callTo,\n _stargateData.callData\n );\n }\n\n emit PartnerSwap(0x0006);\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n function validateDestinationCallFlag(\n ILiFi.BridgeData memory _bridgeData,\n StargateData calldata _stargateData\n ) private pure {\n if (\n (_stargateData.callData.length > 0) !=\n _bridgeData.hasDestinationCall\n ) {\n revert InformationMismatch();\n }\n }\n\n /// Mappings management ///\n\n /// @notice Sets the Layer 0 chain ID for a given chain ID\n /// @param _chainId uint16 of the chain ID\n /// @param _layerZeroChainId uint16 of the Layer 0 chain ID\n /// @dev This is used to map a chain ID to its Layer 0 chain ID\n function setLayerZeroChainId(\n uint256 _chainId,\n uint16 _layerZeroChainId\n ) external {\n LibDiamond.enforceIsContractOwner();\n Storage storage sm = getStorage();\n\n if (!sm.initialized) {\n revert NotInitialized();\n }\n\n sm.layerZeroChainId[_chainId] = _layerZeroChainId;\n emit LayerZeroChainIdSet(_chainId, _layerZeroChainId);\n }\n\n /// @notice Gets the Layer 0 chain ID for a given chain ID\n /// @param _chainId uint256 of the chain ID\n /// @return uint16 of the Layer 0 chain ID\n function getLayerZeroChainId(\n uint256 _chainId\n ) private view returns (uint16) {\n Storage storage sm = getStorage();\n uint16 chainId = sm.layerZeroChainId[_chainId];\n if (chainId == 0) revert UnknownLayerZeroChain();\n return chainId;\n }\n\n function toBytes(address _address) private pure returns (bytes memory) {\n return abi.encodePacked(_address);\n }\n\n /// @dev fetch local storage\n function getStorage() private pure returns (Storage storage s) {\n bytes32 namespace = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n s.slot := namespace\n }\n }\n}\n" + }, + "src/Helpers/CelerIMFacetBase.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ERC20 } from \"solmate/tokens/ERC20.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { InvalidAmount, InformationMismatch } from \"../Errors/GenericErrors.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { MessageSenderLib, MsgDataTypes, IMessageBus } from \"celer-network/contracts/message/libraries/MessageSenderLib.sol\";\nimport { RelayerCelerIM } from \"lifi/Periphery/RelayerCelerIM.sol\";\n\ninterface CelerToken {\n function canonical() external returns (address);\n}\n\ninterface CelerIM {\n /// @param maxSlippage The max slippage accepted, given as percentage in point (pip).\n /// @param nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\n /// @param callTo The address of the contract to be called at destination.\n /// @param callData The encoded calldata with below data\n /// bytes32 transactionId,\n /// LibSwap.SwapData[] memory swapData,\n /// address receiver,\n /// address refundAddress\n /// @param messageBusFee The fee to be paid to CBridge message bus for relaying the message\n /// @param bridgeType Defines the bridge operation type (must be one of the values of CBridge library MsgDataTypes.BridgeSendType)\n struct CelerIMData {\n uint32 maxSlippage;\n uint64 nonce;\n bytes callTo;\n bytes callData;\n uint256 messageBusFee;\n MsgDataTypes.BridgeSendType bridgeType;\n }\n}\n\n/// @title CelerIM Facet Base\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging tokens and data through CBridge\n/// @notice Used to differentiate between contract instances for mutable and immutable diamond as these cannot be shared\n/// @custom:version 2.0.0\nabstract contract CelerIMFacetBase is\n ILiFi,\n ReentrancyGuard,\n SwapperV2,\n Validatable\n{\n /// Storage ///\n\n /// @dev The contract address of the cBridge Message Bus\n IMessageBus private immutable cBridgeMessageBus;\n\n /// @dev The contract address of the RelayerCelerIM\n RelayerCelerIM public immutable relayer;\n\n /// @dev The contract address of the Celer Flow USDC\n address private immutable cfUSDC;\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _messageBus The contract address of the cBridge Message Bus\n /// @param _relayerOwner The address that will become the owner of the RelayerCelerIM contract\n /// @param _diamondAddress The address of the diamond contract that will be connected with the RelayerCelerIM\n /// @param _cfUSDC The contract address of the Celer Flow USDC\n constructor(\n IMessageBus _messageBus,\n address _relayerOwner,\n address _diamondAddress,\n address _cfUSDC\n ) {\n // deploy RelayerCelerIM\n relayer = new RelayerCelerIM(\n address(_messageBus),\n _relayerOwner,\n _diamondAddress\n );\n\n // store arguments in variables\n cBridgeMessageBus = _messageBus;\n cfUSDC = _cfUSDC;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via CBridge\n /// @param _bridgeData The core information needed for bridging\n /// @param _celerIMData Data specific to CelerIM\n function startBridgeTokensViaCelerIM(\n ILiFi.BridgeData memory _bridgeData,\n CelerIM.CelerIMData calldata _celerIMData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n validateDestinationCallFlag(_bridgeData, _celerIMData);\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // Transfer ERC20 tokens directly to relayer\n IERC20 asset = _getRightAsset(_bridgeData.sendingAssetId);\n\n // Deposit ERC20 token\n uint256 prevBalance = asset.balanceOf(address(relayer));\n SafeERC20.safeTransferFrom(\n asset,\n msg.sender,\n address(relayer),\n _bridgeData.minAmount\n );\n\n if (\n asset.balanceOf(address(relayer)) - prevBalance !=\n _bridgeData.minAmount\n ) {\n revert InvalidAmount();\n }\n }\n\n _startBridge(_bridgeData, _celerIMData);\n }\n\n /// @notice Performs a swap before bridging via CBridge\n /// @param _bridgeData The core information needed for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _celerIMData Data specific to CelerIM\n function swapAndStartBridgeTokensViaCelerIM(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n CelerIM.CelerIMData calldata _celerIMData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n validateDestinationCallFlag(_bridgeData, _celerIMData);\n\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n _celerIMData.messageBusFee\n );\n\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // Transfer ERC20 tokens directly to relayer\n IERC20 asset = _getRightAsset(_bridgeData.sendingAssetId);\n\n // Deposit ERC20 token\n uint256 prevBalance = asset.balanceOf(address(relayer));\n SafeERC20.safeTransfer(\n asset,\n address(relayer),\n _bridgeData.minAmount\n );\n\n if (\n asset.balanceOf(address(relayer)) - prevBalance !=\n _bridgeData.minAmount\n ) {\n revert InvalidAmount();\n }\n }\n\n _startBridge(_bridgeData, _celerIMData);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via CBridge\n /// @param _bridgeData The core information needed for bridging\n /// @param _celerIMData Data specific to CBridge\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n CelerIM.CelerIMData calldata _celerIMData\n ) private {\n // Assuming messageBusFee is pre-calculated off-chain and available in _celerIMData\n // Determine correct native asset amount to be forwarded (if so) and send funds to relayer\n uint256 msgValue = LibAsset.isNativeAsset(_bridgeData.sendingAssetId)\n ? _bridgeData.minAmount\n : 0;\n\n // Check if transaction contains a destination call\n if (!_bridgeData.hasDestinationCall) {\n // Case 'no': Simple bridge transfer - Send to receiver\n relayer.sendTokenTransfer{ value: msgValue }(\n _bridgeData,\n _celerIMData\n );\n } else {\n // Case 'yes': Bridge + Destination call - Send to relayer\n\n // save address of original recipient\n address receiver = _bridgeData.receiver;\n\n // Set relayer as a receiver\n _bridgeData.receiver = address(relayer);\n\n // send token transfer\n (bytes32 transferId, address bridgeAddress) = relayer\n .sendTokenTransfer{ value: msgValue }(\n _bridgeData,\n _celerIMData\n );\n\n // Call message bus via relayer incl messageBusFee\n relayer.forwardSendMessageWithTransfer{\n value: _celerIMData.messageBusFee\n }(\n _bridgeData.receiver,\n uint64(_bridgeData.destinationChainId),\n bridgeAddress,\n transferId,\n _celerIMData.callData\n );\n\n // Reset receiver of bridge data for event emission\n _bridgeData.receiver = receiver;\n }\n\n // emit LiFi event\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @dev Get right asset to transfer to relayer.\n /// @param _sendingAssetId The address of asset to bridge.\n /// @return _asset The address of asset to transfer to relayer.\n function _getRightAsset(\n address _sendingAssetId\n ) private returns (IERC20 _asset) {\n if (_sendingAssetId == cfUSDC) {\n // special case for cfUSDC token\n _asset = IERC20(CelerToken(_sendingAssetId).canonical());\n } else {\n // any other ERC20 token\n _asset = IERC20(_sendingAssetId);\n }\n }\n\n function validateDestinationCallFlag(\n ILiFi.BridgeData memory _bridgeData,\n CelerIM.CelerIMData calldata _celerIMData\n ) private pure {\n if (\n (_celerIMData.callData.length > 0) !=\n _bridgeData.hasDestinationCall\n ) {\n revert InformationMismatch();\n }\n }\n}\n" + }, + "src/Facets/StandardizedCallFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\n\n/// @title Standardized Call Facet\n/// @author LIFI https://li.finance ed@li.finance\n/// @notice Allows calling different facet methods through a single standardized entrypoint\n/// @custom:version 1.0.0\ncontract StandardizedCallFacet {\n /// External Methods ///\n\n /// @notice Make a standardized call to a facet\n /// @param callData The calldata to forward to the facet\n function standardizedCall(bytes memory callData) external payable {\n // Fetch the facetAddress from the dimaond's internal storage\n // Cheaper than calling the external facetAddress(selector) method directly\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n address facetAddress = ds\n .selectorToFacetAndPosition[bytes4(callData)]\n .facetAddress;\n\n if (facetAddress == address(0)) {\n revert LibDiamond.FunctionDoesNotExist();\n }\n\n // Execute external function from facet using delegatecall and return any value.\n // solhint-disable-next-line no-inline-assembly\n assembly {\n // execute function call using the facet\n let result := delegatecall(\n gas(),\n facetAddress,\n add(callData, 0x20),\n mload(callData),\n 0,\n 0\n )\n // get any return value\n returndatacopy(0, 0, returndatasize())\n // return any return value or error back to the caller\n switch result\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Interfaces/IConnextHandler.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IConnextHandler {\n /// @notice These are the call parameters that will remain constant between the\n /// two chains. They are supplied on `xcall` and should be asserted on `execute`\n /// @property to - The account that receives funds, in the event of a crosschain call,\n /// will receive funds if the call fails.\n /// @param to - The address you are sending funds (and potentially data) to\n /// @param callData - The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.\n /// @param originDomain - The originating domain (i.e. where `xcall` is called). Must match nomad domain schema\n /// @param destinationDomain - The final domain (i.e. where `execute` / `reconcile` are called). Must match nomad domain schema\n /// @param agent - An address who can execute txs on behalf of `to`, in addition to allowing relayers\n /// @param recovery - The address to send funds to if your `Executor.execute call` fails\n /// @param forceSlow - If true, will take slow liquidity path even if it is not a permissioned call\n /// @param receiveLocal - If true, will use the local nomad asset on the destination instead of adopted.\n /// @param callback - The address on the origin domain of the callback contract\n /// @param callbackFee - The relayer fee to execute the callback\n /// @param relayerFee - The amount of relayer fee the tx called xcall with\n /// @param slippageTol - Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)\n struct CallParams {\n address to;\n bytes callData;\n uint32 originDomain;\n uint32 destinationDomain;\n address agent;\n address recovery;\n bool forceSlow;\n bool receiveLocal;\n address callback;\n uint256 callbackFee;\n uint256 relayerFee;\n uint256 slippageTol;\n }\n\n /// @notice The arguments you supply to the `xcall` function called by user on origin domain\n /// @param params - The CallParams. These are consistent across sending and receiving chains\n /// @param transactingAsset - The asset the caller sent with the transfer. Can be the adopted, canonical,\n /// or the representational asset\n /// @param transactingAmount - The amount of transferring asset supplied by the user in the `xcall`\n /// @param originMinOut - Minimum amount received on swaps for adopted <> local on origin chain\n struct XCallArgs {\n CallParams params;\n address transactingAsset; // Could be adopted, local, or wrapped\n uint256 transactingAmount;\n uint256 originMinOut;\n }\n\n function xcall(\n uint32 destination,\n address recipient,\n address tokenAddress,\n address delegate,\n uint256 amount,\n uint256 slippage,\n bytes memory callData\n ) external payable returns (bytes32);\n\n function xcall(\n uint32 destination,\n address recipient,\n address tokenAddress,\n address delegate,\n uint256 amount,\n uint256 slippage,\n bytes memory callData,\n uint256 _relayerFee\n ) external returns (bytes32);\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Interfaces/IStargateRouter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.17;\n\n// solhint-disable contract-name-camelcase\ninterface IStargateRouter {\n struct lzTxObj {\n uint256 dstGasForCall;\n uint256 dstNativeAmount;\n bytes dstNativeAddr;\n }\n\n /// @notice SwapAmount struct\n /// @param amountLD The amount, in Local Decimals, to be swapped\n /// @param minAmountLD The minimum amount accepted out on destination\n struct SwapAmount {\n uint256 amountLD;\n uint256 minAmountLD;\n }\n\n /// @notice Returns factory address used for creating pools.\n function factory() external view returns (address);\n\n /// @notice Swap assets cross-chain.\n /// @dev Pass (0, 0, \"0x\") to lzTxParams\n /// for 0 additional gasLimit increase, 0 airdrop, at 0x address.\n /// @param dstChainId Destination chainId\n /// @param srcPoolId Source pool id\n /// @param dstPoolId Dest pool id\n /// @param refundAddress Refund adddress. extra gas (if any) is returned to this address\n /// @param amountLD Quantity to swap\n /// @param minAmountLD The min qty you would accept on the destination\n /// @param lzTxParams Additional gas, airdrop data\n /// @param to The address to send the tokens to on the destination\n /// @param payload Additional payload. You can abi.encode() them here\n function swap(\n uint16 dstChainId,\n uint256 srcPoolId,\n uint256 dstPoolId,\n address payable refundAddress,\n uint256 amountLD,\n uint256 minAmountLD,\n lzTxObj memory lzTxParams,\n bytes calldata to,\n bytes calldata payload\n ) external payable;\n\n /// @notice Swap native assets cross-chain.\n /// @param _dstChainId Destination Stargate chainId\n /// @param _refundAddress Refunds additional messageFee to this address\n /// @param _toAddress The receiver of the destination ETH\n /// @param _swapAmount The amount and the minimum swap amount\n /// @param _lzTxParams The LZ tx params\n /// @param _payload The payload to send to the destination\n function swapETHAndCall(\n uint16 _dstChainId,\n address payable _refundAddress,\n bytes calldata _toAddress,\n SwapAmount memory _swapAmount,\n IStargateRouter.lzTxObj memory _lzTxParams,\n bytes calldata _payload\n ) external payable;\n\n /// @notice Returns the native gas fee required for swap.\n function quoteLayerZeroFee(\n uint16 dstChainId,\n uint8 functionType,\n bytes calldata toAddress,\n bytes calldata transferAndCallPayload,\n lzTxObj memory lzTxParams\n ) external view returns (uint256 nativeFee, uint256 zroFee);\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\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 ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "lib/sgn-v2-contracts/contracts/message/libraries/MessageSenderLib.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"../../interfaces/IBridge.sol\";\nimport \"../../interfaces/IOriginalTokenVault.sol\";\nimport \"../../interfaces/IOriginalTokenVaultV2.sol\";\nimport \"../../interfaces/IPeggedTokenBridge.sol\";\nimport \"../../interfaces/IPeggedTokenBridgeV2.sol\";\nimport \"../interfaces/IMessageBus.sol\";\nimport \"./MsgDataTypes.sol\";\n\nlibrary MessageSenderLib {\n using SafeERC20 for IERC20;\n\n // ============== Internal library functions called by apps ==============\n\n /**\n * @notice Sends a message to an app on another chain via MessageBus without an associated transfer.\n * @param _receiver The address of the destination app contract.\n * @param _dstChainId The destination chain ID.\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\n * @param _messageBus The address of the MessageBus on this chain.\n * @param _fee The fee amount to pay to MessageBus.\n */\n function sendMessage(\n address _receiver,\n uint64 _dstChainId,\n bytes memory _message,\n address _messageBus,\n uint256 _fee\n ) internal {\n IMessageBus(_messageBus).sendMessage{value: _fee}(_receiver, _dstChainId, _message);\n }\n\n // Send message to non-evm chain with bytes for receiver address,\n // otherwise same as above.\n function sendMessage(\n bytes calldata _receiver,\n uint64 _dstChainId,\n bytes memory _message,\n address _messageBus,\n uint256 _fee\n ) internal {\n IMessageBus(_messageBus).sendMessage{value: _fee}(_receiver, _dstChainId, _message);\n }\n\n /**\n * @notice Sends a message to an app on another chain via MessageBus with an associated transfer.\n * @param _receiver The address of the destination app contract.\n * @param _token The address of the token to be sent.\n * @param _amount The amount of tokens to be sent.\n * @param _dstChainId The destination chain ID.\n * @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\n * @param _maxSlippage The max slippage accepted, given as percentage in point (pip). Eg. 5000 means 0.5%.\n * Must be greater than minimalMaxSlippage. Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount or the\n * transfer can be refunded. Only applicable to the {MsgDataTypes.BridgeSendType.Liquidity}.\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\n * @param _bridgeSendType One of the {MsgDataTypes.BridgeSendType} enum.\n * @param _messageBus The address of the MessageBus on this chain.\n * @param _fee The fee amount to pay to MessageBus.\n * @return The transfer ID.\n */\n function sendMessageWithTransfer(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce,\n uint32 _maxSlippage,\n bytes memory _message,\n MsgDataTypes.BridgeSendType _bridgeSendType,\n address _messageBus,\n uint256 _fee\n ) internal returns (bytes32) {\n (bytes32 transferId, address bridge) = sendTokenTransfer(\n _receiver,\n _token,\n _amount,\n _dstChainId,\n _nonce,\n _maxSlippage,\n _bridgeSendType,\n _messageBus\n );\n if (_message.length > 0) {\n IMessageBus(_messageBus).sendMessageWithTransfer{value: _fee}(\n _receiver,\n _dstChainId,\n bridge,\n transferId,\n _message\n );\n }\n return transferId;\n }\n\n /**\n * @notice Sends a token transfer via a bridge.\n * @param _receiver The address of the destination app contract.\n * @param _token The address of the token to be sent.\n * @param _amount The amount of tokens to be sent.\n * @param _dstChainId The destination chain ID.\n * @param _nonce A number input to guarantee uniqueness of transferId. Can be timestamp in practice.\n * @param _maxSlippage The max slippage accepted, given as percentage in point (pip). Eg. 5000 means 0.5%.\n * Must be greater than minimalMaxSlippage. Receiver is guaranteed to receive at least (100% - max slippage percentage) * amount or the\n * transfer can be refunded.\n * @param _bridgeSendType One of the {MsgDataTypes.BridgeSendType} enum.\n */\n function sendTokenTransfer(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce,\n uint32 _maxSlippage,\n MsgDataTypes.BridgeSendType _bridgeSendType,\n address _messageBus\n ) internal returns (bytes32 transferId, address bridge) {\n if (_bridgeSendType == MsgDataTypes.BridgeSendType.Liquidity) {\n bridge = IMessageBus(_messageBus).liquidityBridge();\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\n IBridge(bridge).send(_receiver, _token, _amount, _dstChainId, _nonce, _maxSlippage);\n transferId = computeLiqBridgeTransferId(_receiver, _token, _amount, _dstChainId, _nonce);\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegDeposit) {\n bridge = IMessageBus(_messageBus).pegVault();\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\n IOriginalTokenVault(bridge).deposit(_token, _amount, _dstChainId, _receiver, _nonce);\n transferId = computePegV1DepositId(_receiver, _token, _amount, _dstChainId, _nonce);\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegBurn) {\n bridge = IMessageBus(_messageBus).pegBridge();\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\n IPeggedTokenBridge(bridge).burn(_token, _amount, _receiver, _nonce);\n // handle cases where certain tokens do not spend allowance for role-based burn\n IERC20(_token).safeApprove(bridge, 0);\n transferId = computePegV1BurnId(_receiver, _token, _amount, _nonce);\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2Deposit) {\n bridge = IMessageBus(_messageBus).pegVaultV2();\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\n transferId = IOriginalTokenVaultV2(bridge).deposit(_token, _amount, _dstChainId, _receiver, _nonce);\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2Burn) {\n bridge = IMessageBus(_messageBus).pegBridgeV2();\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\n transferId = IPeggedTokenBridgeV2(bridge).burn(_token, _amount, _dstChainId, _receiver, _nonce);\n // handle cases where certain tokens do not spend allowance for role-based burn\n IERC20(_token).safeApprove(bridge, 0);\n } else if (_bridgeSendType == MsgDataTypes.BridgeSendType.PegV2BurnFrom) {\n bridge = IMessageBus(_messageBus).pegBridgeV2();\n IERC20(_token).safeIncreaseAllowance(bridge, _amount);\n transferId = IPeggedTokenBridgeV2(bridge).burnFrom(_token, _amount, _dstChainId, _receiver, _nonce);\n // handle cases where certain tokens do not spend allowance for role-based burn\n IERC20(_token).safeApprove(bridge, 0);\n } else {\n revert(\"bridge type not supported\");\n }\n }\n\n function computeLiqBridgeTransferId(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce\n ) internal view returns (bytes32) {\n return\n keccak256(\n abi.encodePacked(address(this), _receiver, _token, _amount, _dstChainId, _nonce, uint64(block.chainid))\n );\n }\n\n function computePegV1DepositId(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce\n ) internal view returns (bytes32) {\n return\n keccak256(\n abi.encodePacked(address(this), _token, _amount, _dstChainId, _receiver, _nonce, uint64(block.chainid))\n );\n }\n\n function computePegV1BurnId(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _nonce\n ) internal view returns (bytes32) {\n return keccak256(abi.encodePacked(address(this), _token, _amount, _receiver, _nonce, uint64(block.chainid)));\n }\n}\n" + }, + "src/Periphery/RelayerCelerIM.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IERC20, SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { ContractCallNotAllowed, ExternalCallFailed, InvalidConfig, UnAuthorized, WithdrawFailed } from \"../Errors/GenericErrors.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { PeripheryRegistryFacet } from \"../Facets/PeripheryRegistryFacet.sol\";\nimport { IExecutor } from \"../Interfaces/IExecutor.sol\";\nimport { TransferrableOwnership } from \"../Helpers/TransferrableOwnership.sol\";\nimport { IMessageReceiverApp } from \"celer-network/contracts/message/interfaces/IMessageReceiverApp.sol\";\nimport { CelerIM } from \"lifi/Helpers/CelerIMFacetBase.sol\";\nimport { MessageSenderLib, MsgDataTypes, IMessageBus, IOriginalTokenVault, IPeggedTokenBridge, IOriginalTokenVaultV2, IPeggedTokenBridgeV2 } from \"celer-network/contracts/message/libraries/MessageSenderLib.sol\";\nimport { IBridge as ICBridge } from \"celer-network/contracts/interfaces/IBridge.sol\";\n\n/// @title RelayerCelerIM\n/// @author LI.FI (https://li.fi)\n/// @notice Relayer contract for CelerIM that forwards calls and handles refunds on src side and acts receiver on dest\n/// @custom:version 2.0.0\ncontract RelayerCelerIM is ILiFi, TransferrableOwnership {\n using SafeERC20 for IERC20;\n\n /// Storage ///\n\n IMessageBus public cBridgeMessageBus;\n address public diamondAddress;\n\n /// Events ///\n\n event LogWithdraw(\n address indexed _assetAddress,\n address indexed _to,\n uint256 amount\n );\n\n /// Modifiers ///\n\n modifier onlyCBridgeMessageBus() {\n if (msg.sender != address(cBridgeMessageBus)) revert UnAuthorized();\n _;\n }\n modifier onlyDiamond() {\n if (msg.sender != diamondAddress) revert UnAuthorized();\n _;\n }\n\n /// Constructor\n\n constructor(\n address _cBridgeMessageBusAddress,\n address _owner,\n address _diamondAddress\n ) TransferrableOwnership(_owner) {\n owner = _owner;\n cBridgeMessageBus = IMessageBus(_cBridgeMessageBusAddress);\n diamondAddress = _diamondAddress;\n }\n\n /// External Methods ///\n\n /**\n * @notice Called by MessageBus to execute a message with an associated token transfer.\n * The Receiver is guaranteed to have received the right amount of tokens before this function is called.\n * @param * (unused) The address of the source app contract\n * @param _token The address of the token that comes out of the bridge\n * @param _amount The amount of tokens received at this contract through the cross-chain bridge.\n * @param * (unused) The source chain ID where the transfer is originated from\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param * (unused) Address who called the MessageBus execution function\n */\n function executeMessageWithTransfer(\n address,\n address _token,\n uint256 _amount,\n uint64,\n bytes calldata _message,\n address\n )\n external\n payable\n onlyCBridgeMessageBus\n returns (IMessageReceiverApp.ExecutionStatus)\n {\n // decode message\n (\n bytes32 transactionId,\n LibSwap.SwapData[] memory swapData,\n address receiver,\n address refundAddress\n ) = abi.decode(\n _message,\n (bytes32, LibSwap.SwapData[], address, address)\n );\n\n _swapAndCompleteBridgeTokens(\n transactionId,\n swapData,\n _token,\n payable(receiver),\n _amount,\n refundAddress\n );\n\n return IMessageReceiverApp.ExecutionStatus.Success;\n }\n\n /**\n * @notice Called by MessageBus to process refund of the original transfer from this contract.\n * The contract is guaranteed to have received the refund before this function is called.\n * @param _token The token address of the original transfer\n * @param _amount The amount of the original transfer\n * @param _message The same message associated with the original transfer\n * @param * (unused) Address who called the MessageBus execution function\n */\n function executeMessageWithTransferRefund(\n address _token,\n uint256 _amount,\n bytes calldata _message,\n address\n )\n external\n payable\n onlyCBridgeMessageBus\n returns (IMessageReceiverApp.ExecutionStatus)\n {\n (bytes32 transactionId, , , address refundAddress) = abi.decode(\n _message,\n (bytes32, LibSwap.SwapData[], address, address)\n );\n\n // return funds to cBridgeData.refundAddress\n LibAsset.transferAsset(_token, payable(refundAddress), _amount);\n\n emit LiFiTransferRecovered(\n transactionId,\n _token,\n refundAddress,\n _amount,\n block.timestamp\n );\n\n return IMessageReceiverApp.ExecutionStatus.Success;\n }\n\n /**\n * @notice Forwards a call to transfer tokens to cBridge (sent via this contract to ensure that potential refunds are sent here)\n * @param _bridgeData the core information needed for bridging\n * @param _celerIMData data specific to CelerIM\n */\n // solhint-disable-next-line code-complexity\n function sendTokenTransfer(\n ILiFi.BridgeData memory _bridgeData,\n CelerIM.CelerIMData calldata _celerIMData\n )\n external\n payable\n onlyDiamond\n returns (bytes32 transferId, address bridgeAddress)\n {\n // approve to and call correct bridge depending on BridgeSendType\n // @dev copied and slightly adapted from Celer MessageSenderLib\n if (_celerIMData.bridgeType == MsgDataTypes.BridgeSendType.Liquidity) {\n bridgeAddress = cBridgeMessageBus.liquidityBridge();\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // case: native asset bridging\n ICBridge(bridgeAddress).sendNative{\n value: _bridgeData.minAmount\n }(\n _bridgeData.receiver,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _celerIMData.nonce,\n _celerIMData.maxSlippage\n );\n } else {\n // case: ERC20 asset bridging\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n bridgeAddress,\n _bridgeData.minAmount\n );\n // solhint-disable-next-line check-send-result\n ICBridge(bridgeAddress).send(\n _bridgeData.receiver,\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _celerIMData.nonce,\n _celerIMData.maxSlippage\n );\n }\n transferId = MessageSenderLib.computeLiqBridgeTransferId(\n _bridgeData.receiver,\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _celerIMData.nonce\n );\n } else if (\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegDeposit\n ) {\n bridgeAddress = cBridgeMessageBus.pegVault();\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n bridgeAddress,\n _bridgeData.minAmount\n );\n IOriginalTokenVault(bridgeAddress).deposit(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _bridgeData.receiver,\n _celerIMData.nonce\n );\n transferId = MessageSenderLib.computePegV1DepositId(\n _bridgeData.receiver,\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _celerIMData.nonce\n );\n } else if (\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegBurn\n ) {\n bridgeAddress = cBridgeMessageBus.pegBridge();\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n bridgeAddress,\n _bridgeData.minAmount\n );\n IPeggedTokenBridge(bridgeAddress).burn(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n _bridgeData.receiver,\n _celerIMData.nonce\n );\n transferId = MessageSenderLib.computePegV1BurnId(\n _bridgeData.receiver,\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n _celerIMData.nonce\n );\n } else if (\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegV2Deposit\n ) {\n bridgeAddress = cBridgeMessageBus.pegVaultV2();\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // case: native asset bridging\n transferId = IOriginalTokenVaultV2(bridgeAddress)\n .depositNative{ value: _bridgeData.minAmount }(\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _bridgeData.receiver,\n _celerIMData.nonce\n );\n } else {\n // case: ERC20 bridging\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n bridgeAddress,\n _bridgeData.minAmount\n );\n transferId = IOriginalTokenVaultV2(bridgeAddress).deposit(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _bridgeData.receiver,\n _celerIMData.nonce\n );\n }\n } else if (\n _celerIMData.bridgeType == MsgDataTypes.BridgeSendType.PegV2Burn\n ) {\n bridgeAddress = cBridgeMessageBus.pegBridgeV2();\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n bridgeAddress,\n _bridgeData.minAmount\n );\n transferId = IPeggedTokenBridgeV2(bridgeAddress).burn(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _bridgeData.receiver,\n _celerIMData.nonce\n );\n } else if (\n _celerIMData.bridgeType ==\n MsgDataTypes.BridgeSendType.PegV2BurnFrom\n ) {\n bridgeAddress = cBridgeMessageBus.pegBridgeV2();\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n bridgeAddress,\n _bridgeData.minAmount\n );\n transferId = IPeggedTokenBridgeV2(bridgeAddress).burnFrom(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n uint64(_bridgeData.destinationChainId),\n _bridgeData.receiver,\n _celerIMData.nonce\n );\n } else {\n revert InvalidConfig();\n }\n }\n\n /**\n * @notice Forwards a call to the CBridge Messagebus\n * @param _receiver The address of the destination app contract.\n * @param _dstChainId The destination chain ID.\n * @param _srcBridge The bridge contract to send the transfer with.\n * @param _srcTransferId The transfer ID.\n * @param _dstChainId The destination chain ID.\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\n */\n function forwardSendMessageWithTransfer(\n address _receiver,\n uint256 _dstChainId,\n address _srcBridge,\n bytes32 _srcTransferId,\n bytes calldata _message\n ) external payable onlyDiamond {\n cBridgeMessageBus.sendMessageWithTransfer{ value: msg.value }(\n _receiver,\n _dstChainId,\n _srcBridge,\n _srcTransferId,\n _message\n );\n }\n\n // ------------------------------------------------------------------------------------------------\n\n /// Private Methods ///\n\n /// @notice Performs a swap before completing a cross-chain transaction\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swapData array of data needed for swaps\n /// @param assetId token received from the other chain\n /// @param receiver address that will receive tokens in the end\n /// @param amount amount of token\n function _swapAndCompleteBridgeTokens(\n bytes32 _transactionId,\n LibSwap.SwapData[] memory _swapData,\n address assetId,\n address payable receiver,\n uint256 amount,\n address refundAddress\n ) private {\n bool success;\n IExecutor executor = IExecutor(\n PeripheryRegistryFacet(diamondAddress).getPeripheryContract(\n \"Executor\"\n )\n );\n if (LibAsset.isNativeAsset(assetId)) {\n try\n executor.swapAndCompleteBridgeTokens{ value: amount }(\n _transactionId,\n _swapData,\n assetId,\n receiver\n )\n {\n success = true;\n } catch {\n // solhint-disable-next-line avoid-low-level-calls\n (bool fundsSent, ) = refundAddress.call{ value: amount }(\"\");\n if (!fundsSent) {\n revert ExternalCallFailed();\n }\n }\n } else {\n IERC20 token = IERC20(assetId);\n token.safeApprove(address(executor), 0);\n token.safeIncreaseAllowance(address(executor), amount);\n\n try\n executor.swapAndCompleteBridgeTokens(\n _transactionId,\n _swapData,\n assetId,\n receiver\n )\n {\n success = true;\n } catch {\n token.safeTransfer(refundAddress, amount);\n }\n token.safeApprove(address(executor), 0);\n }\n\n if (!success) {\n emit LiFiTransferRecovered(\n _transactionId,\n assetId,\n refundAddress,\n amount,\n block.timestamp\n );\n }\n }\n\n /// @notice Sends remaining token to given receiver address (for refund cases)\n /// @param assetId Address of the token to be withdrawn\n /// @param receiver Address that will receive tokens\n /// @param amount Amount of tokens to be withdrawn\n function withdraw(\n address assetId,\n address payable receiver,\n uint256 amount\n ) external onlyOwner {\n if (LibAsset.isNativeAsset(assetId)) {\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = receiver.call{ value: amount }(\"\");\n if (!success) {\n revert WithdrawFailed();\n }\n } else {\n IERC20(assetId).safeTransfer(receiver, amount);\n }\n emit LogWithdraw(assetId, receiver, amount);\n }\n\n /// @notice Triggers a cBridge refund with calldata produced by cBridge API\n /// @param _callTo The address to execute the calldata on\n /// @param _callData The data to execute\n /// @param _assetAddress Asset to be withdrawn\n /// @param _to Address to withdraw to\n /// @param _amount Amount of asset to withdraw\n function triggerRefund(\n address payable _callTo,\n bytes calldata _callData,\n address _assetAddress,\n address _to,\n uint256 _amount\n ) external onlyOwner {\n bool success;\n\n // make sure that callTo address is either of the cBridge addresses\n if (\n cBridgeMessageBus.liquidityBridge() != _callTo &&\n cBridgeMessageBus.pegBridge() != _callTo &&\n cBridgeMessageBus.pegBridgeV2() != _callTo &&\n cBridgeMessageBus.pegVault() != _callTo &&\n cBridgeMessageBus.pegVaultV2() != _callTo\n ) {\n revert ContractCallNotAllowed();\n }\n\n // call contract\n // solhint-disable-next-line avoid-low-level-calls\n (success, ) = _callTo.call(_callData);\n\n // forward funds to _to address and emit event, if cBridge refund successful\n if (success) {\n address sendTo = (LibUtil.isZeroAddress(_to)) ? msg.sender : _to;\n LibAsset.transferAsset(_assetAddress, payable(sendTo), _amount);\n emit LogWithdraw(_assetAddress, sendTo, _amount);\n } else {\n revert WithdrawFailed();\n }\n }\n\n // required in order to receive native tokens from cBridge facet\n // solhint-disable-next-line no-empty-blocks\n receive() external payable {}\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "lib/sgn-v2-contracts/contracts/interfaces/IBridge.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\ninterface IBridge {\n function send(\n address _receiver,\n address _token,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce,\n uint32 _maxSlippage\n ) external;\n\n function sendNative(\n address _receiver,\n uint256 _amount,\n uint64 _dstChainId,\n uint64 _nonce,\n uint32 _maxSlippage\n ) external payable;\n\n function relay(\n bytes calldata _relayRequest,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external;\n\n function transfers(bytes32 transferId) external view returns (bool);\n\n function withdraws(bytes32 withdrawId) external view returns (bool);\n\n function withdraw(\n bytes calldata _wdmsg,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external;\n\n /**\n * @notice Verifies that a message is signed by a quorum among the signers.\n * @param _msg signed message\n * @param _sigs list of signatures sorted by signer addresses in ascending order\n * @param _signers sorted list of current signers\n * @param _powers powers of current signers\n */\n function verifySigs(\n bytes memory _msg,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external view;\n}\n" + }, + "lib/sgn-v2-contracts/contracts/interfaces/IOriginalTokenVault.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\ninterface IOriginalTokenVault {\n /**\n * @notice Lock original tokens to trigger mint at a remote chain's PeggedTokenBridge\n * @param _token local token address\n * @param _amount locked token amount\n * @param _mintChainId destination chainId to mint tokens\n * @param _mintAccount destination account to receive minted tokens\n * @param _nonce user input to guarantee unique depositId\n */\n function deposit(\n address _token,\n uint256 _amount,\n uint64 _mintChainId,\n address _mintAccount,\n uint64 _nonce\n ) external;\n\n /**\n * @notice Lock native token as original token to trigger mint at a remote chain's PeggedTokenBridge\n * @param _amount locked token amount\n * @param _mintChainId destination chainId to mint tokens\n * @param _mintAccount destination account to receive minted tokens\n * @param _nonce user input to guarantee unique depositId\n */\n function depositNative(\n uint256 _amount,\n uint64 _mintChainId,\n address _mintAccount,\n uint64 _nonce\n ) external payable;\n\n /**\n * @notice Withdraw locked original tokens triggered by a burn at a remote chain's PeggedTokenBridge.\n * @param _request The serialized Withdraw protobuf.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the bridge's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function withdraw(\n bytes calldata _request,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external;\n\n function records(bytes32 recordId) external view returns (bool);\n}\n" + }, + "lib/sgn-v2-contracts/contracts/interfaces/IOriginalTokenVaultV2.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\ninterface IOriginalTokenVaultV2 {\n /**\n * @notice Lock original tokens to trigger mint at a remote chain's PeggedTokenBridge\n * @param _token local token address\n * @param _amount locked token amount\n * @param _mintChainId destination chainId to mint tokens\n * @param _mintAccount destination account to receive minted tokens\n * @param _nonce user input to guarantee unique depositId\n */\n function deposit(\n address _token,\n uint256 _amount,\n uint64 _mintChainId,\n address _mintAccount,\n uint64 _nonce\n ) external returns (bytes32);\n\n /**\n * @notice Lock native token as original token to trigger mint at a remote chain's PeggedTokenBridge\n * @param _amount locked token amount\n * @param _mintChainId destination chainId to mint tokens\n * @param _mintAccount destination account to receive minted tokens\n * @param _nonce user input to guarantee unique depositId\n */\n function depositNative(\n uint256 _amount,\n uint64 _mintChainId,\n address _mintAccount,\n uint64 _nonce\n ) external payable returns (bytes32);\n\n /**\n * @notice Withdraw locked original tokens triggered by a burn at a remote chain's PeggedTokenBridge.\n * @param _request The serialized Withdraw protobuf.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the bridge's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function withdraw(\n bytes calldata _request,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external returns (bytes32);\n\n function records(bytes32 recordId) external view returns (bool);\n}\n" + }, + "lib/sgn-v2-contracts/contracts/interfaces/IPeggedTokenBridge.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\ninterface IPeggedTokenBridge {\n /**\n * @notice Burn tokens to trigger withdrawal at a remote chain's OriginalTokenVault\n * @param _token local token address\n * @param _amount locked token amount\n * @param _withdrawAccount account who withdraw original tokens on the remote chain\n * @param _nonce user input to guarantee unique depositId\n */\n function burn(\n address _token,\n uint256 _amount,\n address _withdrawAccount,\n uint64 _nonce\n ) external;\n\n /**\n * @notice Mint tokens triggered by deposit at a remote chain's OriginalTokenVault.\n * @param _request The serialized Mint protobuf.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the sigsVerifier's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function mint(\n bytes calldata _request,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external;\n\n function records(bytes32 recordId) external view returns (bool);\n}\n" + }, + "lib/sgn-v2-contracts/contracts/interfaces/IPeggedTokenBridgeV2.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\ninterface IPeggedTokenBridgeV2 {\n /**\n * @notice Burn pegged tokens to trigger a cross-chain withdrawal of the original tokens at a remote chain's\n * OriginalTokenVault, or mint at another remote chain\n * @param _token The pegged token address.\n * @param _amount The amount to burn.\n * @param _toChainId If zero, withdraw from original vault; otherwise, the remote chain to mint tokens.\n * @param _toAccount The account to receive tokens on the remote chain\n * @param _nonce A number to guarantee unique depositId. Can be timestamp in practice.\n */\n function burn(\n address _token,\n uint256 _amount,\n uint64 _toChainId,\n address _toAccount,\n uint64 _nonce\n ) external returns (bytes32);\n\n // same with `burn` above, use openzeppelin ERC20Burnable interface\n function burnFrom(\n address _token,\n uint256 _amount,\n uint64 _toChainId,\n address _toAccount,\n uint64 _nonce\n ) external returns (bytes32);\n\n /**\n * @notice Mint tokens triggered by deposit at a remote chain's OriginalTokenVault.\n * @param _request The serialized Mint protobuf.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the sigsVerifier's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function mint(\n bytes calldata _request,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external returns (bytes32);\n\n function records(bytes32 recordId) external view returns (bool);\n}\n" + }, + "lib/sgn-v2-contracts/contracts/message/interfaces/IMessageBus.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\nimport \"../libraries/MsgDataTypes.sol\";\n\ninterface IMessageBus {\n /**\n * @notice Send a message to a contract on another chain.\n * Sender needs to make sure the uniqueness of the message Id, which is computed as\n * hash(type.MessageOnly, sender, receiver, srcChainId, srcTxHash, dstChainId, message).\n * If messages with the same Id are sent, only one of them will succeed at dst chain..\n * A fee is charged in the native gas token.\n * @param _receiver The address of the destination app contract.\n * @param _dstChainId The destination chain ID.\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\n */\n function sendMessage(\n address _receiver,\n uint256 _dstChainId,\n bytes calldata _message\n ) external payable;\n\n // same as above, except that receiver is an non-evm chain address,\n function sendMessage(\n bytes calldata _receiver,\n uint256 _dstChainId,\n bytes calldata _message\n ) external payable;\n\n /**\n * @notice Send a message associated with a token transfer to a contract on another chain.\n * If messages with the same srcTransferId are sent, only one of them will succeed at dst chain..\n * A fee is charged in the native token.\n * @param _receiver The address of the destination app contract.\n * @param _dstChainId The destination chain ID.\n * @param _srcBridge The bridge contract to send the transfer with.\n * @param _srcTransferId The transfer ID.\n * @param _dstChainId The destination chain ID.\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\n */\n function sendMessageWithTransfer(\n address _receiver,\n uint256 _dstChainId,\n address _srcBridge,\n bytes32 _srcTransferId,\n bytes calldata _message\n ) external payable;\n\n /**\n * @notice Execute a message not associated with a transfer.\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the sigsVerifier's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function executeMessage(\n bytes calldata _message,\n MsgDataTypes.RouteInfo calldata _route,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external payable;\n\n /**\n * @notice Execute a message with a successful transfer.\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param _transfer The transfer info.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the sigsVerifier's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function executeMessageWithTransfer(\n bytes calldata _message,\n MsgDataTypes.TransferInfo calldata _transfer,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external payable;\n\n /**\n * @notice Execute a message with a refunded transfer.\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param _transfer The transfer info.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A relay must be signed-off by\n * +2/3 of the sigsVerifier's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function executeMessageWithTransferRefund(\n bytes calldata _message, // the same message associated with the original transfer\n MsgDataTypes.TransferInfo calldata _transfer,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external payable;\n\n /**\n * @notice Withdraws message fee in the form of native gas token.\n * @param _account The address receiving the fee.\n * @param _cumulativeFee The cumulative fee credited to the account. Tracked by SGN.\n * @param _sigs The list of signatures sorted by signing addresses in ascending order. A withdrawal must be\n * signed-off by +2/3 of the sigsVerifier's current signing power to be delivered.\n * @param _signers The sorted list of signers.\n * @param _powers The signing powers of the signers.\n */\n function withdrawFee(\n address _account,\n uint256 _cumulativeFee,\n bytes[] calldata _sigs,\n address[] calldata _signers,\n uint256[] calldata _powers\n ) external;\n\n /**\n * @notice Calculates the required fee for the message.\n * @param _message Arbitrary message bytes to be decoded by the destination app contract.\n @ @return The required fee.\n */\n function calcFee(bytes calldata _message) external view returns (uint256);\n\n function liquidityBridge() external view returns (address);\n\n function pegBridge() external view returns (address);\n\n function pegBridgeV2() external view returns (address);\n\n function pegVault() external view returns (address);\n\n function pegVaultV2() external view returns (address);\n}\n" + }, + "lib/sgn-v2-contracts/contracts/message/libraries/MsgDataTypes.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\nlibrary MsgDataTypes {\n string constant ABORT_PREFIX = \"MSG::ABORT:\";\n\n // bridge operation type at the sender side (src chain)\n enum BridgeSendType {\n Null,\n Liquidity,\n PegDeposit,\n PegBurn,\n PegV2Deposit,\n PegV2Burn,\n PegV2BurnFrom\n }\n\n // bridge operation type at the receiver side (dst chain)\n enum TransferType {\n Null,\n LqRelay, // relay through liquidity bridge\n LqWithdraw, // withdraw from liquidity bridge\n PegMint, // mint through pegged token bridge\n PegWithdraw, // withdraw from original token vault\n PegV2Mint, // mint through pegged token bridge v2\n PegV2Withdraw // withdraw from original token vault v2\n }\n\n enum MsgType {\n MessageWithTransfer,\n MessageOnly\n }\n\n enum TxStatus {\n Null,\n Success,\n Fail,\n Fallback,\n Pending // transient state within a transaction\n }\n\n struct TransferInfo {\n TransferType t;\n address sender;\n address receiver;\n address token;\n uint256 amount;\n uint64 wdseq; // only needed for LqWithdraw (refund)\n uint64 srcChainId;\n bytes32 refId;\n bytes32 srcTxHash; // src chain msg tx hash\n }\n\n struct RouteInfo {\n address sender;\n address receiver;\n uint64 srcChainId;\n bytes32 srcTxHash; // src chain msg tx hash\n }\n\n // used for msg from non-evm chains with longer-bytes address\n struct RouteInfo2 {\n bytes sender;\n address receiver;\n uint64 srcChainId;\n bytes32 srcTxHash;\n }\n\n // combination of RouteInfo and RouteInfo2 for easier processing\n struct Route {\n address sender; // from RouteInfo\n bytes senderBytes; // from RouteInfo2\n address receiver;\n uint64 srcChainId;\n bytes32 srcTxHash;\n }\n\n struct MsgWithTransferExecutionParams {\n bytes message;\n TransferInfo transfer;\n bytes[] sigs;\n address[] signers;\n uint256[] powers;\n }\n\n struct BridgeTransferParams {\n bytes request;\n bytes[] sigs;\n address[] signers;\n uint256[] powers;\n }\n}\n" + }, + "src/Facets/PeripheryRegistryFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\n\n/// @title Periphery Registry Facet\n/// @author LI.FI (https://li.fi)\n/// @notice A simple registry to track LIFI periphery contracts\n/// @custom:version 1.0.0\ncontract PeripheryRegistryFacet {\n /// Storage ///\n\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.facets.periphery_registry\");\n\n /// Types ///\n\n struct Storage {\n mapping(string => address) contracts;\n }\n\n /// Events ///\n\n event PeripheryContractRegistered(string name, address contractAddress);\n\n /// External Methods ///\n\n /// @notice Registers a periphery contract address with a specified name\n /// @param _name the name to register the contract address under\n /// @param _contractAddress the address of the contract to register\n function registerPeripheryContract(\n string calldata _name,\n address _contractAddress\n ) external {\n LibDiamond.enforceIsContractOwner();\n Storage storage s = getStorage();\n s.contracts[_name] = _contractAddress;\n emit PeripheryContractRegistered(_name, _contractAddress);\n }\n\n /// @notice Returns the registered contract address by its name\n /// @param _name the registered name of the contract\n function getPeripheryContract(\n string calldata _name\n ) external view returns (address) {\n return getStorage().contracts[_name];\n }\n\n /// @dev fetch local storage\n function getStorage() private pure returns (Storage storage s) {\n bytes32 namespace = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n s.slot := namespace\n }\n }\n}\n" + }, + "src/Interfaces/IExecutor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\n/// @title Interface for Executor\n/// @author LI.FI (https://li.fi)\ninterface IExecutor {\n /// @notice Performs a swap before completing a cross-chain transaction\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swapData array of data needed for swaps\n /// @param transferredAssetId token received from the other chain\n /// @param receiver address that will receive tokens in the end\n function swapAndCompleteBridgeTokens(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swapData,\n address transferredAssetId,\n address payable receiver\n ) external payable;\n}\n" + }, + "src/Helpers/TransferrableOwnership.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IERC173 } from \"../Interfaces/IERC173.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\n\ncontract TransferrableOwnership is IERC173 {\n address public owner;\n address public pendingOwner;\n\n /// Errors ///\n error UnAuthorized();\n error NoNullOwner();\n error NewOwnerMustNotBeSelf();\n error NoPendingOwnershipTransfer();\n error NotPendingOwner();\n\n /// Events ///\n event OwnershipTransferRequested(\n address indexed _from,\n address indexed _to\n );\n\n constructor(address initialOwner) {\n owner = initialOwner;\n }\n\n modifier onlyOwner() {\n if (msg.sender != owner) revert UnAuthorized();\n _;\n }\n\n /// @notice Initiates transfer of ownership to a new address\n /// @param _newOwner the address to transfer ownership to\n function transferOwnership(address _newOwner) external onlyOwner {\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\n pendingOwner = _newOwner;\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\n }\n\n /// @notice Cancel transfer of ownership\n function cancelOwnershipTransfer() external onlyOwner {\n if (pendingOwner == LibAsset.NULL_ADDRESS)\n revert NoPendingOwnershipTransfer();\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\n function confirmOwnershipTransfer() external {\n address _pendingOwner = pendingOwner;\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n}\n" + }, + "lib/sgn-v2-contracts/contracts/message/interfaces/IMessageReceiverApp.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity >=0.8.0;\n\ninterface IMessageReceiverApp {\n enum ExecutionStatus {\n Fail, // execution failed, finalized\n Success, // execution succeeded, finalized\n Retry // execution rejected, can retry later\n }\n\n /**\n * @notice Called by MessageBus to execute a message\n * @param _sender The address of the source app contract\n * @param _srcChainId The source chain ID where the transfer is originated from\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param _executor Address who called the MessageBus execution function\n */\n function executeMessage(\n address _sender,\n uint64 _srcChainId,\n bytes calldata _message,\n address _executor\n ) external payable returns (ExecutionStatus);\n\n // same as above, except that sender is an non-evm chain address,\n // otherwise same as above.\n function executeMessage(\n bytes calldata _sender,\n uint64 _srcChainId,\n bytes calldata _message,\n address _executor\n ) external payable returns (ExecutionStatus);\n\n /**\n * @notice Called by MessageBus to execute a message with an associated token transfer.\n * The contract is guaranteed to have received the right amount of tokens before this function is called.\n * @param _sender The address of the source app contract\n * @param _token The address of the token that comes out of the bridge\n * @param _amount The amount of tokens received at this contract through the cross-chain bridge.\n * @param _srcChainId The source chain ID where the transfer is originated from\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param _executor Address who called the MessageBus execution function\n */\n function executeMessageWithTransfer(\n address _sender,\n address _token,\n uint256 _amount,\n uint64 _srcChainId,\n bytes calldata _message,\n address _executor\n ) external payable returns (ExecutionStatus);\n\n /**\n * @notice Only called by MessageBus if\n * 1. executeMessageWithTransfer reverts, or\n * 2. executeMessageWithTransfer returns ExecutionStatus.Fail\n * The contract is guaranteed to have received the right amount of tokens before this function is called.\n * @param _sender The address of the source app contract\n * @param _token The address of the token that comes out of the bridge\n * @param _amount The amount of tokens received at this contract through the cross-chain bridge.\n * @param _srcChainId The source chain ID where the transfer is originated from\n * @param _message Arbitrary message bytes originated from and encoded by the source app contract\n * @param _executor Address who called the MessageBus execution function\n */\n function executeMessageWithTransferFallback(\n address _sender,\n address _token,\n uint256 _amount,\n uint64 _srcChainId,\n bytes calldata _message,\n address _executor\n ) external payable returns (ExecutionStatus);\n\n /**\n * @notice Called by MessageBus to process refund of the original transfer from this contract.\n * The contract is guaranteed to have received the refund before this function is called.\n * @param _token The token address of the original transfer\n * @param _amount The amount of the original transfer\n * @param _message The same message associated with the original transfer\n * @param _executor Address who called the MessageBus execution function\n */\n function executeMessageWithTransferRefund(\n address _token,\n uint256 _amount,\n bytes calldata _message,\n address _executor\n ) external payable returns (ExecutionStatus);\n}\n" + }, + "src/Interfaces/IERC173.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\n/// @title ERC-173 Contract Ownership Standard\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\n/* is ERC165 */\ninterface IERC173 {\n /// @dev This emits when ownership of a contract changes.\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n /// @notice Get the address of the owner\n /// @return owner_ The address of the owner.\n function owner() external view returns (address owner_);\n\n /// @notice Set the address of the new owner of the contract\n /// @dev Set _newOwner to address(0) to renounce any ownership.\n /// @param _newOwner The address of the new owner of the contract\n function transferOwnership(address _newOwner) external;\n}\n" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.1.1 + Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \RelayFacet +0x424bdbbaeda89732443fb1b737b6dc194a6ddbd5 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/RelayFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2 } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { ECDSA } from \\\"solady/utils/ECDSA.sol\\\";\\n\\n/// @title Relay Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Relay Protocol\\n/// @custom:version 1.0.0\\ncontract RelayFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n // Receiver for native transfers\\n address public immutable relayReceiver;\\n // Relayer wallet for ERC20 transfers\\n address public immutable relaySolver;\\n\\n /// Storage ///\\n\\n mapping(bytes32 => bool) public consumedIds;\\n\\n /// Types ///\\n\\n /// @dev Relay specific parameters\\n /// @param requestId Relay API request ID\\n /// @param nonEVMReceiver set only if bridging to non-EVM chain\\n /// @params receivingAssetId address of receiving asset\\n /// @params signature attestation signature provided by the Relay solver\\n struct RelayData {\\n bytes32 requestId;\\n bytes32 nonEVMReceiver;\\n bytes32 receivingAssetId;\\n bytes signature;\\n }\\n\\n /// Events ///\\n\\n event BridgeToNonEVMChain(\\n bytes32 indexed transactionId,\\n uint256 indexed destinationChainId,\\n bytes32 receiver\\n );\\n\\n /// Errors ///\\n\\n error InvalidQuote();\\n\\n /// Modifiers ///\\n\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _relayData Data specific to Relay\\n modifier onlyValidQuote(\\n ILiFi.BridgeData memory _bridgeData,\\n RelayData calldata _relayData\\n ) {\\n // Ensure that the id isn't already consumed\\n if (consumedIds[_relayData.requestId]) {\\n revert InvalidQuote();\\n }\\n\\n // Ensure nonEVMAddress is not empty\\n if (\\n _bridgeData.receiver == LibAsset.NON_EVM_ADDRESS &&\\n _relayData.nonEVMReceiver == bytes32(0)\\n ) {\\n revert InvalidQuote();\\n }\\n\\n // Verify that the bridging quote has been signed by the Relay solver\\n // as attested using the attestation API\\n // API URL: https://api.relay.link/requests/{requestId}/signature/v2\\n bytes32 message = ECDSA.toEthSignedMessageHash(\\n keccak256(\\n abi.encodePacked(\\n _relayData.requestId,\\n block.chainid,\\n bytes32(uint256(uint160(address(this)))),\\n bytes32(uint256(uint160(_bridgeData.sendingAssetId))),\\n _getMappedChainId(_bridgeData.destinationChainId),\\n _bridgeData.receiver == LibAsset.NON_EVM_ADDRESS\\n ? _relayData.nonEVMReceiver\\n : bytes32(uint256(uint160(_bridgeData.receiver))),\\n _relayData.receivingAssetId\\n )\\n )\\n );\\n address signer = ECDSA.recover(message, _relayData.signature);\\n if (signer != relaySolver) {\\n revert InvalidQuote();\\n }\\n _;\\n }\\n\\n /// Constructor ///\\n\\n /// @param _relayReceiver The receiver for native transfers\\n /// @param _relaySolver The relayer wallet for ERC20 transfers\\n constructor(address _relayReceiver, address _relaySolver) {\\n relayReceiver = _relayReceiver;\\n relaySolver = _relaySolver;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Relay\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _relayData Data specific to Relay\\n function startBridgeTokensViaRelay(\\n ILiFi.BridgeData calldata _bridgeData,\\n RelayData calldata _relayData\\n )\\n external\\n payable\\n nonReentrant\\n onlyValidQuote(_bridgeData, _relayData)\\n refundExcessNative(payable(msg.sender))\\n validateBridgeData(_bridgeData)\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData, _relayData);\\n }\\n\\n /// @notice Performs a swap before bridging via Relay\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _relayData Data specific to Relay\\n function swapAndStartBridgeTokensViaRelay(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n RelayData calldata _relayData\\n )\\n external\\n payable\\n nonReentrant\\n onlyValidQuote(_bridgeData, _relayData)\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n _startBridge(_bridgeData, _relayData);\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Relay\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _relayData Data specific to Relay\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n RelayData calldata _relayData\\n ) internal {\\n // check if sendingAsset is native or ERC20\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // Native\\n\\n // Send Native to relayReceiver along with requestId as extra data\\n (bool success, bytes memory reason) = relayReceiver.call{\\n value: _bridgeData.minAmount\\n }(abi.encode(_relayData.requestId));\\n if (!success) {\\n revert(LibUtil.getRevertMsg(reason));\\n }\\n } else {\\n // ERC20\\n\\n // We build the calldata from scratch to ensure that we can only\\n // send to the solver address\\n bytes memory transferCallData = bytes.concat(\\n abi.encodeWithSignature(\\n \\\"transfer(address,uint256)\\\",\\n relaySolver,\\n _bridgeData.minAmount\\n ),\\n abi.encode(_relayData.requestId)\\n );\\n (bool success, bytes memory reason) = address(\\n _bridgeData.sendingAssetId\\n ).call(transferCallData);\\n if (!success) {\\n revert(LibUtil.getRevertMsg(reason));\\n }\\n }\\n\\n consumedIds[_relayData.requestId] = true;\\n\\n // Emit special event if bridging to non-EVM chain\\n if (_bridgeData.receiver == LibAsset.NON_EVM_ADDRESS) {\\n emit BridgeToNonEVMChain(\\n _bridgeData.transactionId,\\n _getMappedChainId(_bridgeData.destinationChainId),\\n _relayData.nonEVMReceiver\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @notice get Relay specific chain id for non-EVM chains\\n /// IDs found here https://li.quest/v1/chains?chainTypes=UTXO,SVM\\n /// @param chainId LIFI specific chain id\\n function _getMappedChainId(\\n uint256 chainId\\n ) internal pure returns (uint256) {\\n // Bitcoin\\n if (chainId == 20000000000001) {\\n return 8253038;\\n }\\n\\n // Solana\\n if (chainId == 1151111081099710) {\\n return 792703809;\\n }\\n\\n return chainId;\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity ^0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @custom:version 1.0.1\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n address internal constant NON_EVM_ADDRESS =\\n 0x11f111f111f111F111f111f111F111f111f111F1;\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n LibUtil.revertWith(res);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n\\n function revertWith(bytes memory data) internal pure {\\n assembly {\\n let dataSize := mload(data) // Load the size of the data\\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\\n revert(dataPtr, dataSize) // Revert with the given data\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"lib/solady/src/utils/ECDSA.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n/// @notice Gas optimized ECDSA wrapper.\\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)\\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)\\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)\\n///\\n/// @dev Note:\\n/// - The recovery functions use the ecrecover precompile (0x1).\\n/// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure.\\n/// This is for more safety by default.\\n/// Use the `tryRecover` variants if you need to get the zero address back\\n/// upon recovery failure instead.\\n/// - As of Solady version 0.0.134, all `bytes signature` variants accept both\\n/// regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.\\n/// See: https://eips.ethereum.org/EIPS/eip-2098\\n/// This is for calldata efficiency on smart accounts prevalent on L2s.\\n///\\n/// WARNING! Do NOT use signatures as unique identifiers:\\n/// - Use a nonce in the digest to prevent replay attacks on the same contract.\\n/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.\\n/// EIP-712 also enables readable signing of typed data for better user safety.\\n/// This implementation does NOT check if a signature is non-malleable.\\nlibrary ECDSA {\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* CUSTOM ERRORS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev The signature is invalid.\\n error InvalidSignature();\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* RECOVERY OPERATIONS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.\\n function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := 1\\n let m := mload(0x40) // Cache the free memory pointer.\\n for {} 1 {} {\\n mstore(0x00, hash)\\n mstore(0x40, mload(add(signature, 0x20))) // `r`.\\n if eq(mload(signature), 64) {\\n let vs := mload(add(signature, 0x40))\\n mstore(0x20, add(shr(255, vs), 27)) // `v`.\\n mstore(0x60, shr(1, shl(1, vs))) // `s`.\\n break\\n }\\n if eq(mload(signature), 65) {\\n mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.\\n mstore(0x60, mload(add(signature, 0x40))) // `s`.\\n break\\n }\\n result := 0\\n break\\n }\\n result :=\\n mload(\\n staticcall(\\n gas(), // Amount of gas left for the transaction.\\n result, // Address of `ecrecover`.\\n 0x00, // Start of input.\\n 0x80, // Size of input.\\n 0x01, // Start of output.\\n 0x20 // Size of output.\\n )\\n )\\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\\n if iszero(returndatasize()) {\\n mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x60, 0) // Restore the zero slot.\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.\\n function recoverCalldata(bytes32 hash, bytes calldata signature)\\n internal\\n view\\n returns (address result)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := 1\\n let m := mload(0x40) // Cache the free memory pointer.\\n mstore(0x00, hash)\\n for {} 1 {} {\\n if eq(signature.length, 64) {\\n let vs := calldataload(add(signature.offset, 0x20))\\n mstore(0x20, add(shr(255, vs), 27)) // `v`.\\n mstore(0x40, calldataload(signature.offset)) // `r`.\\n mstore(0x60, shr(1, shl(1, vs))) // `s`.\\n break\\n }\\n if eq(signature.length, 65) {\\n mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.\\n calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.\\n break\\n }\\n result := 0\\n break\\n }\\n result :=\\n mload(\\n staticcall(\\n gas(), // Amount of gas left for the transaction.\\n result, // Address of `ecrecover`.\\n 0x00, // Start of input.\\n 0x80, // Size of input.\\n 0x01, // Start of output.\\n 0x20 // Size of output.\\n )\\n )\\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\\n if iszero(returndatasize()) {\\n mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x60, 0) // Restore the zero slot.\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /// @dev Recovers the signer's address from a message digest `hash`,\\n /// and the EIP-2098 short form signature defined by `r` and `vs`.\\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40) // Cache the free memory pointer.\\n mstore(0x00, hash)\\n mstore(0x20, add(shr(255, vs), 27)) // `v`.\\n mstore(0x40, r)\\n mstore(0x60, shr(1, shl(1, vs))) // `s`.\\n result :=\\n mload(\\n staticcall(\\n gas(), // Amount of gas left for the transaction.\\n 1, // Address of `ecrecover`.\\n 0x00, // Start of input.\\n 0x80, // Size of input.\\n 0x01, // Start of output.\\n 0x20 // Size of output.\\n )\\n )\\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\\n if iszero(returndatasize()) {\\n mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x60, 0) // Restore the zero slot.\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /// @dev Recovers the signer's address from a message digest `hash`,\\n /// and the signature defined by `v`, `r`, `s`.\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)\\n internal\\n view\\n returns (address result)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40) // Cache the free memory pointer.\\n mstore(0x00, hash)\\n mstore(0x20, and(v, 0xff))\\n mstore(0x40, r)\\n mstore(0x60, s)\\n result :=\\n mload(\\n staticcall(\\n gas(), // Amount of gas left for the transaction.\\n 1, // Address of `ecrecover`.\\n 0x00, // Start of input.\\n 0x80, // Size of input.\\n 0x01, // Start of output.\\n 0x20 // Size of output.\\n )\\n )\\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\\n if iszero(returndatasize()) {\\n mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x60, 0) // Restore the zero slot.\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* TRY-RECOVER OPERATIONS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n // WARNING!\\n // These functions will NOT revert upon recovery failure.\\n // Instead, they will return the zero address upon recovery failure.\\n // It is critical that the returned address is NEVER compared against\\n // a zero address (e.g. an uninitialized address variable).\\n\\n /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.\\n function tryRecover(bytes32 hash, bytes memory signature)\\n internal\\n view\\n returns (address result)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := 1\\n let m := mload(0x40) // Cache the free memory pointer.\\n for {} 1 {} {\\n mstore(0x00, hash)\\n mstore(0x40, mload(add(signature, 0x20))) // `r`.\\n if eq(mload(signature), 64) {\\n let vs := mload(add(signature, 0x40))\\n mstore(0x20, add(shr(255, vs), 27)) // `v`.\\n mstore(0x60, shr(1, shl(1, vs))) // `s`.\\n break\\n }\\n if eq(mload(signature), 65) {\\n mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.\\n mstore(0x60, mload(add(signature, 0x40))) // `s`.\\n break\\n }\\n result := 0\\n break\\n }\\n pop(\\n staticcall(\\n gas(), // Amount of gas left for the transaction.\\n result, // Address of `ecrecover`.\\n 0x00, // Start of input.\\n 0x80, // Size of input.\\n 0x40, // Start of output.\\n 0x20 // Size of output.\\n )\\n )\\n mstore(0x60, 0) // Restore the zero slot.\\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\\n result := mload(xor(0x60, returndatasize()))\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.\\n function tryRecoverCalldata(bytes32 hash, bytes calldata signature)\\n internal\\n view\\n returns (address result)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := 1\\n let m := mload(0x40) // Cache the free memory pointer.\\n mstore(0x00, hash)\\n for {} 1 {} {\\n if eq(signature.length, 64) {\\n let vs := calldataload(add(signature.offset, 0x20))\\n mstore(0x20, add(shr(255, vs), 27)) // `v`.\\n mstore(0x40, calldataload(signature.offset)) // `r`.\\n mstore(0x60, shr(1, shl(1, vs))) // `s`.\\n break\\n }\\n if eq(signature.length, 65) {\\n mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.\\n calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.\\n break\\n }\\n result := 0\\n break\\n }\\n pop(\\n staticcall(\\n gas(), // Amount of gas left for the transaction.\\n result, // Address of `ecrecover`.\\n 0x00, // Start of input.\\n 0x80, // Size of input.\\n 0x40, // Start of output.\\n 0x20 // Size of output.\\n )\\n )\\n mstore(0x60, 0) // Restore the zero slot.\\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\\n result := mload(xor(0x60, returndatasize()))\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /// @dev Recovers the signer's address from a message digest `hash`,\\n /// and the EIP-2098 short form signature defined by `r` and `vs`.\\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)\\n internal\\n view\\n returns (address result)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40) // Cache the free memory pointer.\\n mstore(0x00, hash)\\n mstore(0x20, add(shr(255, vs), 27)) // `v`.\\n mstore(0x40, r)\\n mstore(0x60, shr(1, shl(1, vs))) // `s`.\\n pop(\\n staticcall(\\n gas(), // Amount of gas left for the transaction.\\n 1, // Address of `ecrecover`.\\n 0x00, // Start of input.\\n 0x80, // Size of input.\\n 0x40, // Start of output.\\n 0x20 // Size of output.\\n )\\n )\\n mstore(0x60, 0) // Restore the zero slot.\\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\\n result := mload(xor(0x60, returndatasize()))\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /// @dev Recovers the signer's address from a message digest `hash`,\\n /// and the signature defined by `v`, `r`, `s`.\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)\\n internal\\n view\\n returns (address result)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40) // Cache the free memory pointer.\\n mstore(0x00, hash)\\n mstore(0x20, and(v, 0xff))\\n mstore(0x40, r)\\n mstore(0x60, s)\\n pop(\\n staticcall(\\n gas(), // Amount of gas left for the transaction.\\n 1, // Address of `ecrecover`.\\n 0x00, // Start of input.\\n 0x80, // Size of input.\\n 0x40, // Start of output.\\n 0x20 // Size of output.\\n )\\n )\\n mstore(0x60, 0) // Restore the zero slot.\\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\\n result := mload(xor(0x60, returndatasize()))\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* HASHING OPERATIONS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Returns an Ethereum Signed Message, created from a `hash`.\\n /// This produces a hash corresponding to the one signed with the\\n /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)\\n /// JSON-RPC method as part of EIP-191.\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x20, hash) // Store into scratch space for keccak256.\\n mstore(0x00, \\\"\\\\x00\\\\x00\\\\x00\\\\x00\\\\x19Ethereum Signed Message:\\\\n32\\\") // 28 bytes.\\n result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.\\n }\\n }\\n\\n /// @dev Returns an Ethereum Signed Message, created from `s`.\\n /// This produces a hash corresponding to the one signed with the\\n /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)\\n /// JSON-RPC method as part of EIP-191.\\n /// Note: Supports lengths of `s` up to 999999 bytes.\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let sLength := mload(s)\\n let o := 0x20\\n mstore(o, \\\"\\\\x19Ethereum Signed Message:\\\\n\\\") // 26 bytes, zero-right-padded.\\n mstore(0x00, 0x00)\\n // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.\\n for { let temp := sLength } 1 {} {\\n o := sub(o, 1)\\n mstore8(o, add(48, mod(temp, 10)))\\n temp := div(temp, 10)\\n if iszero(temp) { break }\\n }\\n let n := sub(0x3a, o) // Header length: `26 + 32 - o`.\\n // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.\\n returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))\\n mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.\\n result := keccak256(add(s, sub(0x20, n)), add(n, sLength))\\n mstore(s, sLength) // Restore the length.\\n }\\n }\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* EMPTY CALLDATA HELPERS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Returns an empty calldata bytes.\\n function emptySignature() internal pure returns (bytes calldata signature) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n signature.length := 0\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror DiamondIsPaused();\\nerror ExternalCallFailed();\\nerror FunctionDoesNotExist();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"solady/=lib/solady/src/\",\r\n \"permit2/=lib/Permit2/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"Permit2/=lib/Permit2/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"forge-gas-snapshot/=lib/Permit2/lib/forge-gas-snapshot/src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_relayReceiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_relaySolver\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidQuote\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"receiver\",\"type\":\"bytes32\"}],\"name\":\"BridgeToNonEVMChain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"consumedIds\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"relayReceiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"relaySolver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"nonEVMReceiver\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"receivingAssetId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct RelayFacet.RelayData\",\"name\":\"_relayData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaRelay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"nonEVMReceiver\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"receivingAssetId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"struct RelayFacet.RelayData\",\"name\":\"_relayData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaRelay\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "RelayFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "000000000000000000000000a5f565650890fba1824ee0f21ebbbf660a179934000000000000000000000000f70da97812cb96acdf810712aa562db8dfa3dbef", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/RelayFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2 } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { ECDSA } from \"solady/utils/ECDSA.sol\";\n\n/// @title Relay Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Relay Protocol\n/// @custom:version 1.0.0\ncontract RelayFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n // Receiver for native transfers\n address public immutable relayReceiver;\n // Relayer wallet for ERC20 transfers\n address public immutable relaySolver;\n\n /// Storage ///\n\n mapping(bytes32 => bool) public consumedIds;\n\n /// Types ///\n\n /// @dev Relay specific parameters\n /// @param requestId Relay API request ID\n /// @param nonEVMReceiver set only if bridging to non-EVM chain\n /// @params receivingAssetId address of receiving asset\n /// @params signature attestation signature provided by the Relay solver\n struct RelayData {\n bytes32 requestId;\n bytes32 nonEVMReceiver;\n bytes32 receivingAssetId;\n bytes signature;\n }\n\n /// Events ///\n\n event BridgeToNonEVMChain(\n bytes32 indexed transactionId,\n uint256 indexed destinationChainId,\n bytes32 receiver\n );\n\n /// Errors ///\n\n error InvalidQuote();\n\n /// Modifiers ///\n\n /// @param _bridgeData The core information needed for bridging\n /// @param _relayData Data specific to Relay\n modifier onlyValidQuote(\n ILiFi.BridgeData memory _bridgeData,\n RelayData calldata _relayData\n ) {\n // Ensure that the id isn't already consumed\n if (consumedIds[_relayData.requestId]) {\n revert InvalidQuote();\n }\n\n // Ensure nonEVMAddress is not empty\n if (\n _bridgeData.receiver == LibAsset.NON_EVM_ADDRESS &&\n _relayData.nonEVMReceiver == bytes32(0)\n ) {\n revert InvalidQuote();\n }\n\n // Verify that the bridging quote has been signed by the Relay solver\n // as attested using the attestation API\n // API URL: https://api.relay.link/requests/{requestId}/signature/v2\n bytes32 message = ECDSA.toEthSignedMessageHash(\n keccak256(\n abi.encodePacked(\n _relayData.requestId,\n block.chainid,\n bytes32(uint256(uint160(address(this)))),\n bytes32(uint256(uint160(_bridgeData.sendingAssetId))),\n _getMappedChainId(_bridgeData.destinationChainId),\n _bridgeData.receiver == LibAsset.NON_EVM_ADDRESS\n ? _relayData.nonEVMReceiver\n : bytes32(uint256(uint160(_bridgeData.receiver))),\n _relayData.receivingAssetId\n )\n )\n );\n address signer = ECDSA.recover(message, _relayData.signature);\n if (signer != relaySolver) {\n revert InvalidQuote();\n }\n _;\n }\n\n /// Constructor ///\n\n /// @param _relayReceiver The receiver for native transfers\n /// @param _relaySolver The relayer wallet for ERC20 transfers\n constructor(address _relayReceiver, address _relaySolver) {\n relayReceiver = _relayReceiver;\n relaySolver = _relaySolver;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Relay\n /// @param _bridgeData The core information needed for bridging\n /// @param _relayData Data specific to Relay\n function startBridgeTokensViaRelay(\n ILiFi.BridgeData calldata _bridgeData,\n RelayData calldata _relayData\n )\n external\n payable\n nonReentrant\n onlyValidQuote(_bridgeData, _relayData)\n refundExcessNative(payable(msg.sender))\n validateBridgeData(_bridgeData)\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData, _relayData);\n }\n\n /// @notice Performs a swap before bridging via Relay\n /// @param _bridgeData The core information needed for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _relayData Data specific to Relay\n function swapAndStartBridgeTokensViaRelay(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n RelayData calldata _relayData\n )\n external\n payable\n nonReentrant\n onlyValidQuote(_bridgeData, _relayData)\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n _startBridge(_bridgeData, _relayData);\n }\n\n /// Internal Methods ///\n\n /// @dev Contains the business logic for the bridge via Relay\n /// @param _bridgeData The core information needed for bridging\n /// @param _relayData Data specific to Relay\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n RelayData calldata _relayData\n ) internal {\n // check if sendingAsset is native or ERC20\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // Native\n\n // Send Native to relayReceiver along with requestId as extra data\n (bool success, bytes memory reason) = relayReceiver.call{\n value: _bridgeData.minAmount\n }(abi.encode(_relayData.requestId));\n if (!success) {\n revert(LibUtil.getRevertMsg(reason));\n }\n } else {\n // ERC20\n\n // We build the calldata from scratch to ensure that we can only\n // send to the solver address\n bytes memory transferCallData = bytes.concat(\n abi.encodeWithSignature(\n \"transfer(address,uint256)\",\n relaySolver,\n _bridgeData.minAmount\n ),\n abi.encode(_relayData.requestId)\n );\n (bool success, bytes memory reason) = address(\n _bridgeData.sendingAssetId\n ).call(transferCallData);\n if (!success) {\n revert(LibUtil.getRevertMsg(reason));\n }\n }\n\n consumedIds[_relayData.requestId] = true;\n\n // Emit special event if bridging to non-EVM chain\n if (_bridgeData.receiver == LibAsset.NON_EVM_ADDRESS) {\n emit BridgeToNonEVMChain(\n _bridgeData.transactionId,\n _getMappedChainId(_bridgeData.destinationChainId),\n _relayData.nonEVMReceiver\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @notice get Relay specific chain id for non-EVM chains\n /// IDs found here https://li.quest/v1/chains?chainTypes=UTXO,SVM\n /// @param chainId LIFI specific chain id\n function _getMappedChainId(\n uint256 chainId\n ) internal pure returns (uint256) {\n // Bitcoin\n if (chainId == 20000000000001) {\n return 8253038;\n }\n\n // Solana\n if (chainId == 1151111081099710) {\n return 792703809;\n }\n\n return chainId;\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @custom:version 1.0.1\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n address internal constant NON_EVM_ADDRESS =\n 0x11f111f111f111F111f111f111F111f111f111F1;\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n LibUtil.revertWith(res);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n\n function revertWith(bytes memory data) internal pure {\n assembly {\n let dataSize := mload(data) // Load the size of the data\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\n revert(dataPtr, dataSize) // Revert with the given data\n }\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "lib/solady/src/utils/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Gas optimized ECDSA wrapper.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)\n///\n/// @dev Note:\n/// - The recovery functions use the ecrecover precompile (0x1).\n/// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure.\n/// This is for more safety by default.\n/// Use the `tryRecover` variants if you need to get the zero address back\n/// upon recovery failure instead.\n/// - As of Solady version 0.0.134, all `bytes signature` variants accept both\n/// regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.\n/// See: https://eips.ethereum.org/EIPS/eip-2098\n/// This is for calldata efficiency on smart accounts prevalent on L2s.\n///\n/// WARNING! Do NOT use signatures as unique identifiers:\n/// - Use a nonce in the digest to prevent replay attacks on the same contract.\n/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.\n/// EIP-712 also enables readable signing of typed data for better user safety.\n/// This implementation does NOT check if a signature is non-malleable.\nlibrary ECDSA {\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CUSTOM ERRORS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev The signature is invalid.\n error InvalidSignature();\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* RECOVERY OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.\n function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {\n /// @solidity memory-safe-assembly\n assembly {\n result := 1\n let m := mload(0x40) // Cache the free memory pointer.\n for {} 1 {} {\n mstore(0x00, hash)\n mstore(0x40, mload(add(signature, 0x20))) // `r`.\n if eq(mload(signature), 64) {\n let vs := mload(add(signature, 0x40))\n mstore(0x20, add(shr(255, vs), 27)) // `v`.\n mstore(0x60, shr(1, shl(1, vs))) // `s`.\n break\n }\n if eq(mload(signature), 65) {\n mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.\n mstore(0x60, mload(add(signature, 0x40))) // `s`.\n break\n }\n result := 0\n break\n }\n result :=\n mload(\n staticcall(\n gas(), // Amount of gas left for the transaction.\n result, // Address of `ecrecover`.\n 0x00, // Start of input.\n 0x80, // Size of input.\n 0x01, // Start of output.\n 0x20 // Size of output.\n )\n )\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n if iszero(returndatasize()) {\n mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\n revert(0x1c, 0x04)\n }\n mstore(0x60, 0) // Restore the zero slot.\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.\n function recoverCalldata(bytes32 hash, bytes calldata signature)\n internal\n view\n returns (address result)\n {\n /// @solidity memory-safe-assembly\n assembly {\n result := 1\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x00, hash)\n for {} 1 {} {\n if eq(signature.length, 64) {\n let vs := calldataload(add(signature.offset, 0x20))\n mstore(0x20, add(shr(255, vs), 27)) // `v`.\n mstore(0x40, calldataload(signature.offset)) // `r`.\n mstore(0x60, shr(1, shl(1, vs))) // `s`.\n break\n }\n if eq(signature.length, 65) {\n mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.\n calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.\n break\n }\n result := 0\n break\n }\n result :=\n mload(\n staticcall(\n gas(), // Amount of gas left for the transaction.\n result, // Address of `ecrecover`.\n 0x00, // Start of input.\n 0x80, // Size of input.\n 0x01, // Start of output.\n 0x20 // Size of output.\n )\n )\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n if iszero(returndatasize()) {\n mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\n revert(0x1c, 0x04)\n }\n mstore(0x60, 0) // Restore the zero slot.\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Recovers the signer's address from a message digest `hash`,\n /// and the EIP-2098 short form signature defined by `r` and `vs`.\n function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x00, hash)\n mstore(0x20, add(shr(255, vs), 27)) // `v`.\n mstore(0x40, r)\n mstore(0x60, shr(1, shl(1, vs))) // `s`.\n result :=\n mload(\n staticcall(\n gas(), // Amount of gas left for the transaction.\n 1, // Address of `ecrecover`.\n 0x00, // Start of input.\n 0x80, // Size of input.\n 0x01, // Start of output.\n 0x20 // Size of output.\n )\n )\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n if iszero(returndatasize()) {\n mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\n revert(0x1c, 0x04)\n }\n mstore(0x60, 0) // Restore the zero slot.\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Recovers the signer's address from a message digest `hash`,\n /// and the signature defined by `v`, `r`, `s`.\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)\n internal\n view\n returns (address result)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x00, hash)\n mstore(0x20, and(v, 0xff))\n mstore(0x40, r)\n mstore(0x60, s)\n result :=\n mload(\n staticcall(\n gas(), // Amount of gas left for the transaction.\n 1, // Address of `ecrecover`.\n 0x00, // Start of input.\n 0x80, // Size of input.\n 0x01, // Start of output.\n 0x20 // Size of output.\n )\n )\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n if iszero(returndatasize()) {\n mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\n revert(0x1c, 0x04)\n }\n mstore(0x60, 0) // Restore the zero slot.\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* TRY-RECOVER OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n // WARNING!\n // These functions will NOT revert upon recovery failure.\n // Instead, they will return the zero address upon recovery failure.\n // It is critical that the returned address is NEVER compared against\n // a zero address (e.g. an uninitialized address variable).\n\n /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.\n function tryRecover(bytes32 hash, bytes memory signature)\n internal\n view\n returns (address result)\n {\n /// @solidity memory-safe-assembly\n assembly {\n result := 1\n let m := mload(0x40) // Cache the free memory pointer.\n for {} 1 {} {\n mstore(0x00, hash)\n mstore(0x40, mload(add(signature, 0x20))) // `r`.\n if eq(mload(signature), 64) {\n let vs := mload(add(signature, 0x40))\n mstore(0x20, add(shr(255, vs), 27)) // `v`.\n mstore(0x60, shr(1, shl(1, vs))) // `s`.\n break\n }\n if eq(mload(signature), 65) {\n mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.\n mstore(0x60, mload(add(signature, 0x40))) // `s`.\n break\n }\n result := 0\n break\n }\n pop(\n staticcall(\n gas(), // Amount of gas left for the transaction.\n result, // Address of `ecrecover`.\n 0x00, // Start of input.\n 0x80, // Size of input.\n 0x40, // Start of output.\n 0x20 // Size of output.\n )\n )\n mstore(0x60, 0) // Restore the zero slot.\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n result := mload(xor(0x60, returndatasize()))\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.\n function tryRecoverCalldata(bytes32 hash, bytes calldata signature)\n internal\n view\n returns (address result)\n {\n /// @solidity memory-safe-assembly\n assembly {\n result := 1\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x00, hash)\n for {} 1 {} {\n if eq(signature.length, 64) {\n let vs := calldataload(add(signature.offset, 0x20))\n mstore(0x20, add(shr(255, vs), 27)) // `v`.\n mstore(0x40, calldataload(signature.offset)) // `r`.\n mstore(0x60, shr(1, shl(1, vs))) // `s`.\n break\n }\n if eq(signature.length, 65) {\n mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.\n calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.\n break\n }\n result := 0\n break\n }\n pop(\n staticcall(\n gas(), // Amount of gas left for the transaction.\n result, // Address of `ecrecover`.\n 0x00, // Start of input.\n 0x80, // Size of input.\n 0x40, // Start of output.\n 0x20 // Size of output.\n )\n )\n mstore(0x60, 0) // Restore the zero slot.\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n result := mload(xor(0x60, returndatasize()))\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Recovers the signer's address from a message digest `hash`,\n /// and the EIP-2098 short form signature defined by `r` and `vs`.\n function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)\n internal\n view\n returns (address result)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x00, hash)\n mstore(0x20, add(shr(255, vs), 27)) // `v`.\n mstore(0x40, r)\n mstore(0x60, shr(1, shl(1, vs))) // `s`.\n pop(\n staticcall(\n gas(), // Amount of gas left for the transaction.\n 1, // Address of `ecrecover`.\n 0x00, // Start of input.\n 0x80, // Size of input.\n 0x40, // Start of output.\n 0x20 // Size of output.\n )\n )\n mstore(0x60, 0) // Restore the zero slot.\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n result := mload(xor(0x60, returndatasize()))\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Recovers the signer's address from a message digest `hash`,\n /// and the signature defined by `v`, `r`, `s`.\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)\n internal\n view\n returns (address result)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x00, hash)\n mstore(0x20, and(v, 0xff))\n mstore(0x40, r)\n mstore(0x60, s)\n pop(\n staticcall(\n gas(), // Amount of gas left for the transaction.\n 1, // Address of `ecrecover`.\n 0x00, // Start of input.\n 0x80, // Size of input.\n 0x40, // Start of output.\n 0x20 // Size of output.\n )\n )\n mstore(0x60, 0) // Restore the zero slot.\n // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n result := mload(xor(0x60, returndatasize()))\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* HASHING OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Returns an Ethereum Signed Message, created from a `hash`.\n /// This produces a hash corresponding to the one signed with the\n /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)\n /// JSON-RPC method as part of EIP-191.\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x20, hash) // Store into scratch space for keccak256.\n mstore(0x00, \"\\x00\\x00\\x00\\x00\\x19Ethereum Signed Message:\\n32\") // 28 bytes.\n result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.\n }\n }\n\n /// @dev Returns an Ethereum Signed Message, created from `s`.\n /// This produces a hash corresponding to the one signed with the\n /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)\n /// JSON-RPC method as part of EIP-191.\n /// Note: Supports lengths of `s` up to 999999 bytes.\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {\n /// @solidity memory-safe-assembly\n assembly {\n let sLength := mload(s)\n let o := 0x20\n mstore(o, \"\\x19Ethereum Signed Message:\\n\") // 26 bytes, zero-right-padded.\n mstore(0x00, 0x00)\n // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.\n for { let temp := sLength } 1 {} {\n o := sub(o, 1)\n mstore8(o, add(48, mod(temp, 10)))\n temp := div(temp, 10)\n if iszero(temp) { break }\n }\n let n := sub(0x3a, o) // Header length: `26 + 32 - o`.\n // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.\n returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))\n mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.\n result := keccak256(add(s, sub(0x20, n)), add(n, sLength))\n mstore(s, sLength) // Restore the length.\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* EMPTY CALLDATA HELPERS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Returns an empty calldata bytes.\n function emptySignature() internal pure returns (bytes calldata signature) {\n /// @solidity memory-safe-assembly\n assembly {\n signature.length := 0\n }\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror DiamondIsPaused();\nerror ExternalCallFailed();\nerror FunctionDoesNotExist();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "solady/=lib/solady/src/", + "permit2/=lib/Permit2/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "Permit2/=lib/Permit2/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "forge-gas-snapshot/=lib/Permit2/lib/forge-gas-snapshot/src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... |ThorSwapFacet +0x3c0727e3ab7baf3a4205f518f1b7570d68da19ba +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/ThorSwapFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IThorSwap } from \\\"../Interfaces/IThorSwap.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { SwapperV2 } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { ContractCallNotAllowed } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title ThorSwap Facet\\n/// @author Li.Finance (https://li.finance)\\n/// @notice Provides functionality for bridging through ThorSwap\\n/// @custom:version 1.2.1\\ncontract ThorSwapFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n address private immutable thorchainRouter;\\n\\n address private constant DEPRECATED_RUNE =\\n 0x3155BA85D5F96b2d030a4966AF206230e46849cb;\\n\\n /// @notice The struct for the ThorSwap data.\\n /// @param vault The Thorchain vault address\\n /// @param memo The memo to send to Thorchain for the swap\\n /// @param expiration The expiration time for the swap\\n struct ThorSwapData {\\n address vault;\\n string memo;\\n uint256 expiration;\\n }\\n\\n error DeprecatedToken();\\n\\n /// @notice Initializes the ThorSwap contract\\n constructor(address _thorchainRouter) {\\n thorchainRouter = _thorchainRouter;\\n }\\n\\n /// @notice Bridge tokens to another chain via ThorSwap\\n /// @param _bridgeData The bridge data struct\\n /// @param _thorSwapData The ThorSwap data struct\\n function startBridgeTokensViaThorSwap(\\n ILiFi.BridgeData memory _bridgeData,\\n ThorSwapData calldata _thorSwapData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n validateBridgeData(_bridgeData)\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData, _thorSwapData);\\n }\\n\\n /// @notice Bridge tokens to another chain via ThorSwap\\n /// @param _bridgeData The bridge data struct\\n /// @param _swapData The swap data struct\\n /// @param _thorSwapData The ThorSwap data struct\\n function swapAndStartBridgeTokensViaThorSwap(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n ThorSwapData calldata _thorSwapData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n _startBridge(_bridgeData, _thorSwapData);\\n }\\n\\n /// @notice Bridge tokens to another chain via ThorSwap\\n /// @param _bridgeData The bridge data struct\\n /// @param _thorSwapData The thorSwap data struct for ThorSwap specicific data\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n ThorSwapData calldata _thorSwapData\\n ) internal {\\n if (\\n block.chainid == 1 && _bridgeData.sendingAssetId == DEPRECATED_RUNE\\n ) {\\n revert DeprecatedToken();\\n }\\n\\n IERC20 sendingAssetId = IERC20(_bridgeData.sendingAssetId);\\n bool isNative = LibAsset.isNativeAsset(address(sendingAssetId));\\n\\n if (!isNative) {\\n LibAsset.maxApproveERC20(\\n sendingAssetId,\\n thorchainRouter,\\n _bridgeData.minAmount\\n );\\n }\\n IThorSwap(thorchainRouter).depositWithExpiry{\\n value: isNative ? _bridgeData.minAmount : 0\\n }(\\n _thorSwapData.vault,\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n _thorSwapData.memo,\\n _thorSwapData.expiration\\n );\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IThorSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\n/// @title ThorSwap Interface\\ninterface IThorSwap {\\n // Thorchain router\\n function depositWithExpiry(\\n address vault,\\n address asset,\\n uint256 amount,\\n string calldata memo,\\n uint256 expiration\\n ) external payable;\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity ^0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @custom:version 1.0.2\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n address internal constant NON_EVM_ADDRESS =\\n 0x11f111f111f111F111f111f111F111f111f111F1;\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.forceApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n LibUtil.revertWith(res);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror DiamondIsPaused();\\nerror ExternalCallFailed();\\nerror FunctionDoesNotExist();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n\\n function revertWith(bytes memory data) internal pure {\\n assembly {\\n let dataSize := mload(data) // Load the size of the data\\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\\n revert(dataPtr, dataSize) // Revert with the given data\\n }\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"solady/=lib/solady/src/\",\r\n \"permit2/=lib/Permit2/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"Permit2/=lib/Permit2/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"forge-gas-snapshot/=lib/Permit2/lib/forge-gas-snapshot/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_thorchainRouter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DeprecatedToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vault\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"}],\"internalType\":\"struct ThorSwapFacet.ThorSwapData\",\"name\":\"_thorSwapData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaThorSwap\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vault\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"expiration\",\"type\":\"uint256\"}],\"internalType\":\"struct ThorSwapFacet.ThorSwapData\",\"name\":\"_thorSwapData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaThorSwap\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "ThorSwapFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "000000000000000000000000d37bbe5744d730a1d98d8dc97c42f0ca46ad7146", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/ThorSwapFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IThorSwap } from \"../Interfaces/IThorSwap.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { SwapperV2 } from \"../Helpers/SwapperV2.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { ContractCallNotAllowed } from \"../Errors/GenericErrors.sol\";\n\n/// @title ThorSwap Facet\n/// @author Li.Finance (https://li.finance)\n/// @notice Provides functionality for bridging through ThorSwap\n/// @custom:version 1.2.1\ncontract ThorSwapFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n address private immutable thorchainRouter;\n\n address private constant DEPRECATED_RUNE =\n 0x3155BA85D5F96b2d030a4966AF206230e46849cb;\n\n /// @notice The struct for the ThorSwap data.\n /// @param vault The Thorchain vault address\n /// @param memo The memo to send to Thorchain for the swap\n /// @param expiration The expiration time for the swap\n struct ThorSwapData {\n address vault;\n string memo;\n uint256 expiration;\n }\n\n error DeprecatedToken();\n\n /// @notice Initializes the ThorSwap contract\n constructor(address _thorchainRouter) {\n thorchainRouter = _thorchainRouter;\n }\n\n /// @notice Bridge tokens to another chain via ThorSwap\n /// @param _bridgeData The bridge data struct\n /// @param _thorSwapData The ThorSwap data struct\n function startBridgeTokensViaThorSwap(\n ILiFi.BridgeData memory _bridgeData,\n ThorSwapData calldata _thorSwapData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n validateBridgeData(_bridgeData)\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData, _thorSwapData);\n }\n\n /// @notice Bridge tokens to another chain via ThorSwap\n /// @param _bridgeData The bridge data struct\n /// @param _swapData The swap data struct\n /// @param _thorSwapData The ThorSwap data struct\n function swapAndStartBridgeTokensViaThorSwap(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n ThorSwapData calldata _thorSwapData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n _startBridge(_bridgeData, _thorSwapData);\n }\n\n /// @notice Bridge tokens to another chain via ThorSwap\n /// @param _bridgeData The bridge data struct\n /// @param _thorSwapData The thorSwap data struct for ThorSwap specicific data\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n ThorSwapData calldata _thorSwapData\n ) internal {\n if (\n block.chainid == 1 && _bridgeData.sendingAssetId == DEPRECATED_RUNE\n ) {\n revert DeprecatedToken();\n }\n\n IERC20 sendingAssetId = IERC20(_bridgeData.sendingAssetId);\n bool isNative = LibAsset.isNativeAsset(address(sendingAssetId));\n\n if (!isNative) {\n LibAsset.maxApproveERC20(\n sendingAssetId,\n thorchainRouter,\n _bridgeData.minAmount\n );\n }\n IThorSwap(thorchainRouter).depositWithExpiry{\n value: isNative ? _bridgeData.minAmount : 0\n }(\n _thorSwapData.vault,\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n _thorSwapData.memo,\n _thorSwapData.expiration\n );\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IThorSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\n/// @title ThorSwap Interface\ninterface IThorSwap {\n // Thorchain router\n function depositWithExpiry(\n address vault,\n address asset,\n uint256 amount,\n string calldata memo,\n uint256 expiration\n ) external payable;\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @custom:version 1.0.2\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n address internal constant NON_EVM_ADDRESS =\n 0x11f111f111f111F111f111f111F111f111f111F1;\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.forceApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n LibUtil.revertWith(res);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror DiamondIsPaused();\nerror ExternalCallFailed();\nerror FunctionDoesNotExist();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n\n function revertWith(bytes memory data) internal pure {\n assembly {\n let dataSize := mload(data) // Load the size of the data\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\n revert(dataPtr, dataSize) // Revert with the given data\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "solady/=lib/solady/src/", + "permit2/=lib/Permit2/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "Permit2/=lib/Permit2/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "forge-gas-snapshot/=lib/Permit2/lib/forge-gas-snapshot/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +1.2.1 + Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... -WithdrawFacet +0x711e80a9c1eb906d9ae9d37e5432e6e7aceeda0b +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/WithdrawFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAccess } from \\\"../Libraries/LibAccess.sol\\\";\\nimport { NotAContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Withdraw Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Allows admin to withdraw funds that are kept in the contract by accident\\n/// @custom:version 1.0.0\\ncontract WithdrawFacet {\\n /// Errors ///\\n\\n error WithdrawFailed();\\n\\n /// Events ///\\n\\n event LogWithdraw(\\n address indexed _assetAddress,\\n address _to,\\n uint256 amount\\n );\\n\\n /// External Methods ///\\n\\n /// @notice Execute call data and withdraw asset.\\n /// @param _callTo The address to execute the calldata on.\\n /// @param _callData The data to execute.\\n /// @param _assetAddress Asset to be withdrawn.\\n /// @param _to address to withdraw to.\\n /// @param _amount amount of asset to withdraw.\\n function executeCallAndWithdraw(\\n address payable _callTo,\\n bytes calldata _callData,\\n address _assetAddress,\\n address _to,\\n uint256 _amount\\n ) external {\\n if (msg.sender != LibDiamond.contractOwner()) {\\n LibAccess.enforceAccessControl();\\n }\\n\\n // Check if the _callTo is a contract\\n bool success;\\n bool isContract = LibAsset.isContract(_callTo);\\n if (!isContract) revert NotAContract();\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (success, ) = _callTo.call(_callData);\\n\\n if (success) {\\n _withdrawAsset(_assetAddress, _to, _amount);\\n } else {\\n revert WithdrawFailed();\\n }\\n }\\n\\n /// @notice Withdraw asset.\\n /// @param _assetAddress Asset to be withdrawn.\\n /// @param _to address to withdraw to.\\n /// @param _amount amount of asset to withdraw.\\n function withdraw(\\n address _assetAddress,\\n address _to,\\n uint256 _amount\\n ) external {\\n if (msg.sender != LibDiamond.contractOwner()) {\\n LibAccess.enforceAccessControl();\\n }\\n _withdrawAsset(_assetAddress, _to, _amount);\\n }\\n\\n /// Internal Methods ///\\n\\n /// @notice Withdraw asset.\\n /// @param _assetAddress Asset to be withdrawn.\\n /// @param _to address to withdraw to.\\n /// @param _amount amount of asset to withdraw.\\n function _withdrawAsset(\\n address _assetAddress,\\n address _to,\\n uint256 _amount\\n ) internal {\\n address sendTo = (LibUtil.isZeroAddress(_to)) ? msg.sender : _to;\\n LibAsset.transferAsset(_assetAddress, payable(sendTo), _amount);\\n emit LogWithdraw(_assetAddress, sendTo, _amount);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAccess.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { CannotAuthoriseSelf, UnAuthorized } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Access Library\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for managing method level access control\\nlibrary LibAccess {\\n /// Types ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.access.management\\\");\\n\\n /// Storage ///\\n struct AccessStorage {\\n mapping(bytes4 => mapping(address => bool)) execAccess;\\n }\\n\\n /// Events ///\\n event AccessGranted(address indexed account, bytes4 indexed method);\\n event AccessRevoked(address indexed account, bytes4 indexed method);\\n\\n /// @dev Fetch local storage\\n function accessStorage()\\n internal\\n pure\\n returns (AccessStorage storage accStor)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n accStor.slot := position\\n }\\n }\\n\\n /// @notice Gives an address permission to execute a method\\n /// @param selector The method selector to execute\\n /// @param executor The address to grant permission to\\n function addAccess(bytes4 selector, address executor) internal {\\n if (executor == address(this)) {\\n revert CannotAuthoriseSelf();\\n }\\n AccessStorage storage accStor = accessStorage();\\n accStor.execAccess[selector][executor] = true;\\n emit AccessGranted(executor, selector);\\n }\\n\\n /// @notice Revokes permission to execute a method\\n /// @param selector The method selector to execute\\n /// @param executor The address to revoke permission from\\n function removeAccess(bytes4 selector, address executor) internal {\\n AccessStorage storage accStor = accessStorage();\\n accStor.execAccess[selector][executor] = false;\\n emit AccessRevoked(executor, selector);\\n }\\n\\n /// @notice Enforces access control by reverting if `msg.sender`\\n /// has not been given permission to execute `msg.sig`\\n function enforceAccessControl() internal view {\\n AccessStorage storage accStor = accessStorage();\\n if (accStor.execAccess[msg.sig][msg.sender] != true)\\n revert UnAuthorized();\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"lifi/=src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"test/=test/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnAuthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WithdrawFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_assetAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LogWithdraw\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_callTo\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_callData\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"_assetAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"executeCallAndWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_assetAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ContractName: "WithdrawFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "", + EVMVersion: "Default", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/WithdrawFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAccess } from \"../Libraries/LibAccess.sol\";\nimport { NotAContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Withdraw Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Allows admin to withdraw funds that are kept in the contract by accident\n/// @custom:version 1.0.0\ncontract WithdrawFacet {\n /// Errors ///\n\n error WithdrawFailed();\n\n /// Events ///\n\n event LogWithdraw(\n address indexed _assetAddress,\n address _to,\n uint256 amount\n );\n\n /// External Methods ///\n\n /// @notice Execute call data and withdraw asset.\n /// @param _callTo The address to execute the calldata on.\n /// @param _callData The data to execute.\n /// @param _assetAddress Asset to be withdrawn.\n /// @param _to address to withdraw to.\n /// @param _amount amount of asset to withdraw.\n function executeCallAndWithdraw(\n address payable _callTo,\n bytes calldata _callData,\n address _assetAddress,\n address _to,\n uint256 _amount\n ) external {\n if (msg.sender != LibDiamond.contractOwner()) {\n LibAccess.enforceAccessControl();\n }\n\n // Check if the _callTo is a contract\n bool success;\n bool isContract = LibAsset.isContract(_callTo);\n if (!isContract) revert NotAContract();\n\n // solhint-disable-next-line avoid-low-level-calls\n (success, ) = _callTo.call(_callData);\n\n if (success) {\n _withdrawAsset(_assetAddress, _to, _amount);\n } else {\n revert WithdrawFailed();\n }\n }\n\n /// @notice Withdraw asset.\n /// @param _assetAddress Asset to be withdrawn.\n /// @param _to address to withdraw to.\n /// @param _amount amount of asset to withdraw.\n function withdraw(\n address _assetAddress,\n address _to,\n uint256 _amount\n ) external {\n if (msg.sender != LibDiamond.contractOwner()) {\n LibAccess.enforceAccessControl();\n }\n _withdrawAsset(_assetAddress, _to, _amount);\n }\n\n /// Internal Methods ///\n\n /// @notice Withdraw asset.\n /// @param _assetAddress Asset to be withdrawn.\n /// @param _to address to withdraw to.\n /// @param _amount amount of asset to withdraw.\n function _withdrawAsset(\n address _assetAddress,\n address _to,\n uint256 _amount\n ) internal {\n address sendTo = (LibUtil.isZeroAddress(_to)) ? msg.sender : _to;\n LibAsset.transferAsset(_assetAddress, payable(sendTo), _amount);\n emit LogWithdraw(_assetAddress, sendTo, _amount);\n }\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Libraries/LibAccess.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { CannotAuthoriseSelf, UnAuthorized } from \"../Errors/GenericErrors.sol\";\n\n/// @title Access Library\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for managing method level access control\nlibrary LibAccess {\n /// Types ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.access.management\");\n\n /// Storage ///\n struct AccessStorage {\n mapping(bytes4 => mapping(address => bool)) execAccess;\n }\n\n /// Events ///\n event AccessGranted(address indexed account, bytes4 indexed method);\n event AccessRevoked(address indexed account, bytes4 indexed method);\n\n /// @dev Fetch local storage\n function accessStorage()\n internal\n pure\n returns (AccessStorage storage accStor)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n accStor.slot := position\n }\n }\n\n /// @notice Gives an address permission to execute a method\n /// @param selector The method selector to execute\n /// @param executor The address to grant permission to\n function addAccess(bytes4 selector, address executor) internal {\n if (executor == address(this)) {\n revert CannotAuthoriseSelf();\n }\n AccessStorage storage accStor = accessStorage();\n accStor.execAccess[selector][executor] = true;\n emit AccessGranted(executor, selector);\n }\n\n /// @notice Revokes permission to execute a method\n /// @param selector The method selector to execute\n /// @param executor The address to revoke permission from\n function removeAccess(bytes4 selector, address executor) internal {\n AccessStorage storage accStor = accessStorage();\n accStor.execAccess[selector][executor] = false;\n emit AccessRevoked(executor, selector);\n }\n\n /// @notice Enforces access control by reverting if `msg.sender`\n /// has not been given permission to execute `msg.sig`\n function enforceAccessControl() internal view {\n AccessStorage storage accStor = accessStorage();\n if (accStor.execAccess[msg.sig][msg.sender] != true)\n revert UnAuthorized();\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "@uniswap/=node_modules/@uniswap/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "ds-test/=lib/ds-test/src/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "forge-std/=lib/forge-std/src/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "hardhat/=node_modules/hardhat/", + "lifi/=src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solmate/=lib/solmate/src/", + "test/=test/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... /GenericSwapFacetV3 +0x31a9b1835864706af10103b31ea2b79bdb995f5f +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/GenericSwapFacetV3.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ContractCallNotAllowed, CumulativeSlippageTooHigh, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ERC20, SafeTransferLib } from \\\"solmate/utils/SafeTransferLib.sol\\\";\\nimport { console2 } from \\\"forge-std/console2.sol\\\";\\n\\n/// @title GenericSwapFacetV3\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides gas-optimized functionality for fee collection and for swapping through any APPROVED DEX\\n/// @dev Can only execute calldata for APPROVED function selectors\\n/// @custom:version 1.0.0\\ncontract GenericSwapFacetV3 is ILiFi {\\n using SafeTransferLib for ERC20;\\n\\n /// External Methods ///\\n\\n // SINGLE SWAPS\\n\\n /// @notice Performs a single swap from an ERC20 token to another ERC20 token\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _integrator the name of the integrator\\n /// @param _referrer the address of the referrer\\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\\n /// @param _minAmountOut the minimum amount of the final asset to receive\\n /// @param _swapData an object containing swap related data to perform swaps before bridging\\n function swapTokensSingleV3ERC20ToERC20(\\n bytes32 _transactionId,\\n string calldata _integrator,\\n string calldata _referrer,\\n address payable _receiver,\\n uint256 _minAmountOut,\\n LibSwap.SwapData calldata _swapData\\n ) external {\\n _depositAndSwapERC20Single(_swapData, _receiver);\\n\\n address receivingAssetId = _swapData.receivingAssetId;\\n address sendingAssetId = _swapData.sendingAssetId;\\n\\n // get contract's balance (which will be sent in full to user)\\n uint256 amountReceived = ERC20(receivingAssetId).balanceOf(\\n address(this)\\n );\\n\\n // ensure that minAmountOut was received\\n if (amountReceived < _minAmountOut)\\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\\n\\n // transfer funds to receiver\\n ERC20(receivingAssetId).safeTransfer(_receiver, amountReceived);\\n\\n // emit events (both required for tracking)\\n uint256 fromAmount = _swapData.fromAmount;\\n emit LibSwap.AssetSwapped(\\n _transactionId,\\n _swapData.callTo,\\n sendingAssetId,\\n receivingAssetId,\\n fromAmount,\\n amountReceived,\\n block.timestamp\\n );\\n\\n emit ILiFi.LiFiGenericSwapCompleted(\\n _transactionId,\\n _integrator,\\n _referrer,\\n _receiver,\\n sendingAssetId,\\n receivingAssetId,\\n fromAmount,\\n amountReceived\\n );\\n }\\n\\n /// @notice Performs a single swap from an ERC20 token to the network's native token\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _integrator the name of the integrator\\n /// @param _referrer the address of the referrer\\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\\n /// @param _minAmountOut the minimum amount of the final asset to receive\\n /// @param _swapData an object containing swap related data to perform swaps before bridging\\n function swapTokensSingleV3ERC20ToNative(\\n bytes32 _transactionId,\\n string calldata _integrator,\\n string calldata _referrer,\\n address payable _receiver,\\n uint256 _minAmountOut,\\n LibSwap.SwapData calldata _swapData\\n ) external {\\n _depositAndSwapERC20Single(_swapData, _receiver);\\n\\n // get contract's balance (which will be sent in full to user)\\n uint256 amountReceived = address(this).balance;\\n\\n // ensure that minAmountOut was received\\n if (amountReceived < _minAmountOut)\\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\\n\\n // transfer funds to receiver\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = _receiver.call{ value: amountReceived }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n\\n // emit events (both required for tracking)\\n address sendingAssetId = _swapData.sendingAssetId;\\n uint256 fromAmount = _swapData.fromAmount;\\n emit LibSwap.AssetSwapped(\\n _transactionId,\\n _swapData.callTo,\\n sendingAssetId,\\n address(0),\\n fromAmount,\\n amountReceived,\\n block.timestamp\\n );\\n\\n emit ILiFi.LiFiGenericSwapCompleted(\\n _transactionId,\\n _integrator,\\n _referrer,\\n _receiver,\\n sendingAssetId,\\n address(0),\\n fromAmount,\\n amountReceived\\n );\\n }\\n\\n /// @notice Performs a single swap from the network's native token to ERC20 token\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _integrator the name of the integrator\\n /// @param _referrer the address of the referrer\\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\\n /// @param _minAmountOut the minimum amount of the final asset to receive\\n /// @param _swapData an object containing swap related data to perform swaps before bridging\\n function swapTokensSingleV3NativeToERC20(\\n bytes32 _transactionId,\\n string calldata _integrator,\\n string calldata _referrer,\\n address payable _receiver,\\n uint256 _minAmountOut,\\n LibSwap.SwapData calldata _swapData\\n ) external payable {\\n address callTo = _swapData.callTo;\\n // ensure that contract (callTo) and function selector are whitelisted\\n if (\\n !(LibAllowList.contractIsAllowed(callTo) &&\\n LibAllowList.selectorIsAllowed(bytes4(_swapData.callData[:4])))\\n ) revert ContractCallNotAllowed();\\n\\n // execute swap\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = callTo.call{ value: msg.value }(\\n _swapData.callData\\n );\\n if (!success) {\\n LibUtil.revertWith(res);\\n }\\n\\n _returnPositiveSlippageNative(_receiver);\\n\\n // get contract's balance (which will be sent in full to user)\\n address receivingAssetId = _swapData.receivingAssetId;\\n uint256 amountReceived = ERC20(receivingAssetId).balanceOf(\\n address(this)\\n );\\n\\n // ensure that minAmountOut was received\\n if (amountReceived < _minAmountOut)\\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\\n\\n // transfer funds to receiver\\n ERC20(receivingAssetId).safeTransfer(_receiver, amountReceived);\\n\\n // emit events (both required for tracking)\\n uint256 fromAmount = _swapData.fromAmount;\\n emit LibSwap.AssetSwapped(\\n _transactionId,\\n callTo,\\n address(0),\\n receivingAssetId,\\n fromAmount,\\n amountReceived,\\n block.timestamp\\n );\\n\\n emit ILiFi.LiFiGenericSwapCompleted(\\n _transactionId,\\n _integrator,\\n _referrer,\\n _receiver,\\n address(0),\\n receivingAssetId,\\n fromAmount,\\n amountReceived\\n );\\n }\\n\\n // MULTIPLE SWAPS\\n\\n /// @notice Performs multiple swaps in one transaction, starting with ERC20 and ending with native\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _integrator the name of the integrator\\n /// @param _referrer the address of the referrer\\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\\n /// @param _minAmountOut the minimum amount of the final asset to receive\\n /// @param _swapData an object containing swap related data to perform swaps before bridging\\n function swapTokensMultipleV3ERC20ToNative(\\n bytes32 _transactionId,\\n string calldata _integrator,\\n string calldata _referrer,\\n address payable _receiver,\\n uint256 _minAmountOut,\\n LibSwap.SwapData[] calldata _swapData\\n ) external {\\n _depositMultipleERC20Tokens(_swapData);\\n _executeSwaps(_swapData, _transactionId, _receiver);\\n _transferNativeTokensAndEmitEvent(\\n _transactionId,\\n _integrator,\\n _referrer,\\n _receiver,\\n _minAmountOut,\\n _swapData\\n );\\n }\\n\\n /// @notice Performs multiple swaps in one transaction, starting with ERC20 and ending with ERC20\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _integrator the name of the integrator\\n /// @param _referrer the address of the referrer\\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\\n /// @param _minAmountOut the minimum amount of the final asset to receive\\n /// @param _swapData an object containing swap related data to perform swaps before bridging\\n function swapTokensMultipleV3ERC20ToERC20(\\n bytes32 _transactionId,\\n string calldata _integrator,\\n string calldata _referrer,\\n address payable _receiver,\\n uint256 _minAmountOut,\\n LibSwap.SwapData[] calldata _swapData\\n ) external {\\n _depositMultipleERC20Tokens(_swapData);\\n _executeSwaps(_swapData, _transactionId, _receiver);\\n _transferERC20TokensAndEmitEvent(\\n _transactionId,\\n _integrator,\\n _referrer,\\n _receiver,\\n _minAmountOut,\\n _swapData\\n );\\n }\\n\\n /// @notice Performs multiple swaps in one transaction, starting with native and ending with ERC20\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _integrator the name of the integrator\\n /// @param _referrer the address of the referrer\\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\\n /// @param _minAmountOut the minimum amount of the final asset to receive\\n /// @param _swapData an object containing swap related data to perform swaps before bridging\\n function swapTokensMultipleV3NativeToERC20(\\n bytes32 _transactionId,\\n string calldata _integrator,\\n string calldata _referrer,\\n address payable _receiver,\\n uint256 _minAmountOut,\\n LibSwap.SwapData[] calldata _swapData\\n ) external payable {\\n _executeSwaps(_swapData, _transactionId, _receiver);\\n _transferERC20TokensAndEmitEvent(\\n _transactionId,\\n _integrator,\\n _referrer,\\n _receiver,\\n _minAmountOut,\\n _swapData\\n );\\n }\\n\\n /// Private helper methods ///\\n function _depositMultipleERC20Tokens(\\n LibSwap.SwapData[] calldata _swapData\\n ) private {\\n // initialize variables before loop to save gas\\n uint256 numOfSwaps = _swapData.length;\\n LibSwap.SwapData calldata currentSwap;\\n\\n // go through all swaps and deposit tokens, where required\\n for (uint256 i = 0; i < numOfSwaps; ) {\\n currentSwap = _swapData[i];\\n if (currentSwap.requiresDeposit) {\\n // we will not check msg.value as tx will fail anyway if not enough value available\\n // thus we only deposit ERC20 tokens here\\n ERC20(currentSwap.sendingAssetId).safeTransferFrom(\\n msg.sender,\\n address(this),\\n currentSwap.fromAmount\\n );\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n function _depositAndSwapERC20Single(\\n LibSwap.SwapData calldata _swapData,\\n address _receiver\\n ) private {\\n ERC20 sendingAsset = ERC20(_swapData.sendingAssetId);\\n uint256 fromAmount = _swapData.fromAmount;\\n // deposit funds\\n sendingAsset.safeTransferFrom(msg.sender, address(this), fromAmount);\\n\\n // ensure that contract (callTo) and function selector are whitelisted\\n address callTo = _swapData.callTo;\\n address approveTo = _swapData.approveTo;\\n bytes calldata callData = _swapData.callData;\\n if (\\n !(LibAllowList.contractIsAllowed(callTo) &&\\n LibAllowList.selectorIsAllowed(bytes4(callData[:4])))\\n ) revert ContractCallNotAllowed();\\n\\n // ensure that approveTo address is also whitelisted if it differs from callTo\\n if (approveTo != callTo && !LibAllowList.contractIsAllowed(approveTo))\\n revert ContractCallNotAllowed();\\n\\n // check if the current allowance is sufficient\\n uint256 currentAllowance = sendingAsset.allowance(\\n address(this),\\n approveTo\\n );\\n\\n // check if existing allowance is sufficient\\n if (currentAllowance < fromAmount) {\\n // check if is non-zero, set to 0 if not\\n if (currentAllowance != 0) sendingAsset.safeApprove(approveTo, 0);\\n // set allowance to uint max to avoid future approvals\\n sendingAsset.safeApprove(approveTo, type(uint256).max);\\n }\\n\\n // execute swap\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = callTo.call(callData);\\n if (!success) {\\n LibUtil.revertWith(res);\\n }\\n\\n _returnPositiveSlippageERC20(sendingAsset, _receiver);\\n }\\n\\n // @dev: this function will not work with swapData that has multiple swaps with the same sendingAssetId\\n // as the _returnPositiveSlippage... functionality will refund all remaining tokens after the first swap\\n // We accept this fact since the use case is not common yet. As an alternative you can always use the\\n // \\\"swapTokensGeneric\\\" function of the original GenericSwapFacet\\n function _executeSwaps(\\n LibSwap.SwapData[] calldata _swapData,\\n bytes32 _transactionId,\\n address _receiver\\n ) private {\\n // initialize variables before loop to save gas\\n uint256 numOfSwaps = _swapData.length;\\n ERC20 sendingAsset;\\n address sendingAssetId;\\n address receivingAssetId;\\n LibSwap.SwapData calldata currentSwap;\\n bool success;\\n bytes memory returnData;\\n uint256 currentAllowance;\\n\\n // go through all swaps\\n for (uint256 i = 0; i < numOfSwaps; ) {\\n currentSwap = _swapData[i];\\n sendingAssetId = currentSwap.sendingAssetId;\\n sendingAsset = ERC20(currentSwap.sendingAssetId);\\n receivingAssetId = currentSwap.receivingAssetId;\\n\\n // check if callTo address is whitelisted\\n if (\\n !LibAllowList.contractIsAllowed(currentSwap.callTo) ||\\n !LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n )\\n ) {\\n revert ContractCallNotAllowed();\\n }\\n\\n // if approveTo address is different to callTo, check if it's whitelisted, too\\n if (\\n currentSwap.approveTo != currentSwap.callTo &&\\n !LibAllowList.contractIsAllowed(currentSwap.approveTo)\\n ) {\\n revert ContractCallNotAllowed();\\n }\\n\\n if (LibAsset.isNativeAsset(sendingAssetId)) {\\n // Native\\n // execute the swap\\n (success, returnData) = currentSwap.callTo.call{\\n value: currentSwap.fromAmount\\n }(currentSwap.callData);\\n if (!success) {\\n LibUtil.revertWith(returnData);\\n }\\n\\n // return any potential leftover sendingAsset tokens\\n // but only for swaps, not for fee collections (otherwise the whole amount would be returned before the actual swap)\\n if (sendingAssetId != receivingAssetId)\\n _returnPositiveSlippageNative(_receiver);\\n } else {\\n // ERC20\\n // check if the current allowance is sufficient\\n currentAllowance = sendingAsset.allowance(\\n address(this),\\n currentSwap.approveTo\\n );\\n if (currentAllowance < currentSwap.fromAmount) {\\n sendingAsset.safeApprove(currentSwap.approveTo, 0);\\n sendingAsset.safeApprove(\\n currentSwap.approveTo,\\n type(uint256).max\\n );\\n }\\n\\n // execute the swap\\n (success, returnData) = currentSwap.callTo.call(\\n currentSwap.callData\\n );\\n if (!success) {\\n LibUtil.revertWith(returnData);\\n }\\n\\n // return any potential leftover sendingAsset tokens\\n // but only for swaps, not for fee collections (otherwise the whole amount would be returned before the actual swap)\\n if (sendingAssetId != receivingAssetId)\\n _returnPositiveSlippageERC20(sendingAsset, _receiver);\\n }\\n\\n // emit AssetSwapped event\\n // @dev: this event might in some cases emit inaccurate information. e.g. if a token is swapped and this contract already held a balance of the receivingAsset\\n // then the event will show swapOutputAmount + existingBalance as toAmount. We accept this potential inaccuracy in return for gas savings and may update this\\n // at a later stage when the described use case becomes more common\\n emit LibSwap.AssetSwapped(\\n _transactionId,\\n currentSwap.callTo,\\n sendingAssetId,\\n receivingAssetId,\\n currentSwap.fromAmount,\\n LibAsset.isNativeAsset(receivingAssetId)\\n ? address(this).balance\\n : ERC20(receivingAssetId).balanceOf(address(this)),\\n block.timestamp\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n function _transferERC20TokensAndEmitEvent(\\n bytes32 _transactionId,\\n string calldata _integrator,\\n string calldata _referrer,\\n address payable _receiver,\\n uint256 _minAmountOut,\\n LibSwap.SwapData[] calldata _swapData\\n ) private {\\n // determine the end result of the swap\\n address finalAssetId = _swapData[_swapData.length - 1]\\n .receivingAssetId;\\n uint256 amountReceived = ERC20(finalAssetId).balanceOf(address(this));\\n\\n // make sure minAmountOut was received\\n if (amountReceived < _minAmountOut)\\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\\n\\n // transfer to receiver\\n ERC20(finalAssetId).safeTransfer(_receiver, amountReceived);\\n\\n // emit event\\n emit ILiFi.LiFiGenericSwapCompleted(\\n _transactionId,\\n _integrator,\\n _referrer,\\n _receiver,\\n _swapData[0].sendingAssetId,\\n finalAssetId,\\n _swapData[0].fromAmount,\\n amountReceived\\n );\\n }\\n\\n function _transferNativeTokensAndEmitEvent(\\n bytes32 _transactionId,\\n string calldata _integrator,\\n string calldata _referrer,\\n address payable _receiver,\\n uint256 _minAmountOut,\\n LibSwap.SwapData[] calldata _swapData\\n ) private {\\n console2.log(\\\"in _transferNativeTokensAndEmitEvent\\\");\\n uint256 amountReceived = address(this).balance;\\n\\n // make sure minAmountOut was received\\n if (amountReceived < _minAmountOut)\\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\\n\\n // transfer funds to receiver\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = _receiver.call{ value: amountReceived }(\\\"\\\");\\n if (!success) {\\n console2.log(\\\"HEYA\\\");\\n revert NativeAssetTransferFailed();\\n }\\n\\n // emit event\\n emit ILiFi.LiFiGenericSwapCompleted(\\n _transactionId,\\n _integrator,\\n _referrer,\\n _receiver,\\n _swapData[0].sendingAssetId,\\n address(0),\\n _swapData[0].fromAmount,\\n amountReceived\\n );\\n }\\n\\n // returns any unused 'sendingAsset' tokens (=> positive slippage) to the receiver address\\n function _returnPositiveSlippageERC20(\\n ERC20 sendingAsset,\\n address receiver\\n ) private {\\n // if a balance exists in sendingAsset, it must be positive slippage\\n if (address(sendingAsset) != address(0)) {\\n uint256 sendingAssetBalance = sendingAsset.balanceOf(\\n address(this)\\n );\\n\\n if (sendingAssetBalance > 0) {\\n sendingAsset.safeTransfer(receiver, sendingAssetBalance);\\n }\\n }\\n }\\n\\n // returns any unused native tokens (=> positive slippage) to the receiver address\\n function _returnPositiveSlippageNative(address receiver) private {\\n // if a native balance exists in sendingAsset, it must be positive slippage\\n uint256 nativeBalance = address(this).balance;\\n\\n if (nativeBalance > 0) {\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = receiver.call{ value: nativeBalance }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n\\n function revertWith(bytes memory data) internal pure {\\n assembly {\\n let dataSize := mload(data) // Load the size of the data\\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\\n revert(dataPtr, dataSize) // Revert with the given data\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n LibUtil.revertWith(res);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/solmate/src/utils/SafeTransferLib.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\nimport {ERC20} from \\\"../tokens/ERC20.sol\\\";\\n\\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\\nlibrary SafeTransferLib {\\n /*//////////////////////////////////////////////////////////////\\n ETH OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferETH(address to, uint256 amount) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Transfer the ETH and store if it succeeded or not.\\n success := call(gas(), to, amount, 0, 0, 0, 0)\\n }\\n\\n require(success, \\\"ETH_TRANSFER_FAILED\\\");\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferFrom(\\n ERC20 token,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), from) // Append the \\\"from\\\" argument.\\n mstore(add(freeMemoryPointer, 36), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 68), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FROM_FAILED\\\");\\n }\\n\\n function safeTransfer(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FAILED\\\");\\n }\\n\\n function safeApprove(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"APPROVE_FAILED\\\");\\n }\\n}\\n\"\r\n },\r\n \"lib/forge-std/src/console2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.22 <0.9.0;\\n\\n/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should\\n/// use `int256` and `uint256`. This modified version fixes that. This version is recommended\\n/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in\\n/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.\\n/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178\\nlibrary console2 {\\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n function _castLogPayloadViewToPure(\\n function(bytes memory) internal view fnIn\\n ) internal pure returns (function(bytes memory) internal pure fnOut) {\\n assembly {\\n fnOut := fnIn\\n }\\n }\\n\\n function _sendLogPayload(bytes memory payload) internal pure {\\n _castLogPayloadViewToPure(_sendLogPayloadView)(payload);\\n }\\n\\n function _sendLogPayloadView(bytes memory payload) private view {\\n uint256 payloadLength = payload.length;\\n address consoleAddress = CONSOLE_ADDRESS;\\n /// @solidity memory-safe-assembly\\n assembly {\\n let payloadStart := add(payload, 32)\\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n }\\n }\\n\\n function log() internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n }\\n\\n function logInt(int256 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(int256)\\\", p0));\\n }\\n\\n function logUint(uint256 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256)\\\", p0));\\n }\\n\\n function logString(string memory p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n }\\n\\n function logBool(bool p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n }\\n\\n function logAddress(address p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n }\\n\\n function logBytes(bytes memory p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n }\\n\\n function logBytes1(bytes1 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n }\\n\\n function logBytes2(bytes2 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n }\\n\\n function logBytes3(bytes3 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n }\\n\\n function logBytes4(bytes4 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n }\\n\\n function logBytes5(bytes5 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n }\\n\\n function logBytes6(bytes6 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n }\\n\\n function logBytes7(bytes7 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n }\\n\\n function logBytes8(bytes8 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n }\\n\\n function logBytes9(bytes9 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n }\\n\\n function logBytes10(bytes10 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n }\\n\\n function logBytes11(bytes11 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n }\\n\\n function logBytes12(bytes12 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n }\\n\\n function logBytes13(bytes13 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n }\\n\\n function logBytes14(bytes14 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n }\\n\\n function logBytes15(bytes15 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n }\\n\\n function logBytes16(bytes16 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n }\\n\\n function logBytes17(bytes17 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n }\\n\\n function logBytes18(bytes18 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n }\\n\\n function logBytes19(bytes19 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n }\\n\\n function logBytes20(bytes20 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n }\\n\\n function logBytes21(bytes21 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n }\\n\\n function logBytes22(bytes22 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n }\\n\\n function logBytes23(bytes23 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n }\\n\\n function logBytes24(bytes24 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n }\\n\\n function logBytes25(bytes25 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n }\\n\\n function logBytes26(bytes26 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n }\\n\\n function logBytes27(bytes27 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n }\\n\\n function logBytes28(bytes28 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n }\\n\\n function logBytes29(bytes29 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n }\\n\\n function logBytes30(bytes30 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n }\\n\\n function logBytes31(bytes31 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n }\\n\\n function logBytes32(bytes32 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n }\\n\\n function log(uint256 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256)\\\", p0));\\n }\\n\\n function log(int256 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(int256)\\\", p0));\\n }\\n\\n function log(string memory p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n }\\n\\n function log(bool p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n }\\n\\n function log(address p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n }\\n\\n function log(uint256 p0, uint256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256)\\\", p0, p1));\\n }\\n\\n function log(uint256 p0, string memory p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string)\\\", p0, p1));\\n }\\n\\n function log(uint256 p0, bool p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool)\\\", p0, p1));\\n }\\n\\n function log(uint256 p0, address p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, uint256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, int256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,int256)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, string memory p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, bool p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, address p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n }\\n\\n function log(bool p0, uint256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256)\\\", p0, p1));\\n }\\n\\n function log(bool p0, string memory p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n }\\n\\n function log(bool p0, bool p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n }\\n\\n function log(bool p0, address p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n }\\n\\n function log(address p0, uint256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256)\\\", p0, p1));\\n }\\n\\n function log(address p0, string memory p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n }\\n\\n function log(address p0, bool p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n }\\n\\n function log(address p0, address p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, bool p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, address p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, address p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, string memory p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, bool p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, bool p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, address p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, address p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, address p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, uint256 p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, string memory p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, string memory p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, bool p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, bool p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, bool p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, address p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, address p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, address p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, address p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, uint256 p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, uint256 p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, string memory p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, string memory p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, string memory p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, bool p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, bool p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, bool p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, bool p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, address p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, address p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, address p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, address p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n}\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/solmate/src/tokens/ERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\\nabstract contract ERC20 {\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /*//////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string public name;\\n\\n string public symbol;\\n\\n uint8 public immutable decimals;\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 public totalSupply;\\n\\n mapping(address => uint256) public balanceOf;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 internal immutable INITIAL_CHAIN_ID;\\n\\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\\n\\n mapping(address => uint256) public nonces;\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n constructor(\\n string memory _name,\\n string memory _symbol,\\n uint8 _decimals\\n ) {\\n name = _name;\\n symbol = _symbol;\\n decimals = _decimals;\\n\\n INITIAL_CHAIN_ID = block.chainid;\\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function approve(address spender, uint256 amount) public virtual returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n\\n return true;\\n }\\n\\n function transfer(address to, uint256 amount) public virtual returns (bool) {\\n balanceOf[msg.sender] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(msg.sender, to, amount);\\n\\n return true;\\n }\\n\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual returns (bool) {\\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\\n\\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\\n\\n balanceOf[from] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n return true;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 LOGIC\\n //////////////////////////////////////////////////////////////*/\\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 ) public virtual {\\n require(deadline >= block.timestamp, \\\"PERMIT_DEADLINE_EXPIRED\\\");\\n\\n // Unchecked because the only math done is incrementing\\n // the owner's nonce which cannot realistically overflow.\\n unchecked {\\n address recoveredAddress = ecrecover(\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR(),\\n keccak256(\\n abi.encode(\\n keccak256(\\n \\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\"\\n ),\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n require(recoveredAddress != address(0) && recoveredAddress == owner, \\\"INVALID_SIGNER\\\");\\n\\n allowance[recoveredAddress][spender] = value;\\n }\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\\n }\\n\\n function computeDomainSeparator() internal view virtual returns (bytes32) {\\n return\\n keccak256(\\n abi.encode(\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"),\\n keccak256(bytes(name)),\\n keccak256(\\\"1\\\"),\\n block.chainid,\\n address(this)\\n )\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _mint(address to, uint256 amount) internal virtual {\\n totalSupply += amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(address(0), to, amount);\\n }\\n\\n function _burn(address from, uint256 amount) internal virtual {\\n balanceOf[from] -= amount;\\n\\n // Cannot underflow because a user's balance\\n // will never be larger than the total supply.\\n unchecked {\\n totalSupply -= amount;\\n }\\n\\n emit Transfer(from, address(0), amount);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"_integrator\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_referrer\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minAmountOut\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"}],\"name\":\"swapTokensMultipleV3ERC20ToERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"_integrator\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_referrer\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minAmountOut\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"}],\"name\":\"swapTokensMultipleV3ERC20ToNative\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"_integrator\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_referrer\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minAmountOut\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"}],\"name\":\"swapTokensMultipleV3NativeToERC20\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"_integrator\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_referrer\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minAmountOut\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData\",\"name\":\"_swapData\",\"type\":\"tuple\"}],\"name\":\"swapTokensSingleV3ERC20ToERC20\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"_integrator\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_referrer\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minAmountOut\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData\",\"name\":\"_swapData\",\"type\":\"tuple\"}],\"name\":\"swapTokensSingleV3ERC20ToNative\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"_integrator\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_referrer\",\"type\":\"string\"},{\"internalType\":\"address payable\",\"name\":\"_receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minAmountOut\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData\",\"name\":\"_swapData\",\"type\":\"tuple\"}],\"name\":\"swapTokensSingleV3NativeToERC20\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "GenericSwapFacetV3", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/GenericSwapFacetV3.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { ContractCallNotAllowed, CumulativeSlippageTooHigh, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport { ERC20, SafeTransferLib } from \"solmate/utils/SafeTransferLib.sol\";\nimport { console2 } from \"forge-std/console2.sol\";\n\n/// @title GenericSwapFacetV3\n/// @author LI.FI (https://li.fi)\n/// @notice Provides gas-optimized functionality for fee collection and for swapping through any APPROVED DEX\n/// @dev Can only execute calldata for APPROVED function selectors\n/// @custom:version 1.0.0\ncontract GenericSwapFacetV3 is ILiFi {\n using SafeTransferLib for ERC20;\n\n /// External Methods ///\n\n // SINGLE SWAPS\n\n /// @notice Performs a single swap from an ERC20 token to another ERC20 token\n /// @param _transactionId the transaction id associated with the operation\n /// @param _integrator the name of the integrator\n /// @param _referrer the address of the referrer\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\n /// @param _minAmountOut the minimum amount of the final asset to receive\n /// @param _swapData an object containing swap related data to perform swaps before bridging\n function swapTokensSingleV3ERC20ToERC20(\n bytes32 _transactionId,\n string calldata _integrator,\n string calldata _referrer,\n address payable _receiver,\n uint256 _minAmountOut,\n LibSwap.SwapData calldata _swapData\n ) external {\n _depositAndSwapERC20Single(_swapData, _receiver);\n\n address receivingAssetId = _swapData.receivingAssetId;\n address sendingAssetId = _swapData.sendingAssetId;\n\n // get contract's balance (which will be sent in full to user)\n uint256 amountReceived = ERC20(receivingAssetId).balanceOf(\n address(this)\n );\n\n // ensure that minAmountOut was received\n if (amountReceived < _minAmountOut)\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\n\n // transfer funds to receiver\n ERC20(receivingAssetId).safeTransfer(_receiver, amountReceived);\n\n // emit events (both required for tracking)\n uint256 fromAmount = _swapData.fromAmount;\n emit LibSwap.AssetSwapped(\n _transactionId,\n _swapData.callTo,\n sendingAssetId,\n receivingAssetId,\n fromAmount,\n amountReceived,\n block.timestamp\n );\n\n emit ILiFi.LiFiGenericSwapCompleted(\n _transactionId,\n _integrator,\n _referrer,\n _receiver,\n sendingAssetId,\n receivingAssetId,\n fromAmount,\n amountReceived\n );\n }\n\n /// @notice Performs a single swap from an ERC20 token to the network's native token\n /// @param _transactionId the transaction id associated with the operation\n /// @param _integrator the name of the integrator\n /// @param _referrer the address of the referrer\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\n /// @param _minAmountOut the minimum amount of the final asset to receive\n /// @param _swapData an object containing swap related data to perform swaps before bridging\n function swapTokensSingleV3ERC20ToNative(\n bytes32 _transactionId,\n string calldata _integrator,\n string calldata _referrer,\n address payable _receiver,\n uint256 _minAmountOut,\n LibSwap.SwapData calldata _swapData\n ) external {\n _depositAndSwapERC20Single(_swapData, _receiver);\n\n // get contract's balance (which will be sent in full to user)\n uint256 amountReceived = address(this).balance;\n\n // ensure that minAmountOut was received\n if (amountReceived < _minAmountOut)\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\n\n // transfer funds to receiver\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = _receiver.call{ value: amountReceived }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n\n // emit events (both required for tracking)\n address sendingAssetId = _swapData.sendingAssetId;\n uint256 fromAmount = _swapData.fromAmount;\n emit LibSwap.AssetSwapped(\n _transactionId,\n _swapData.callTo,\n sendingAssetId,\n address(0),\n fromAmount,\n amountReceived,\n block.timestamp\n );\n\n emit ILiFi.LiFiGenericSwapCompleted(\n _transactionId,\n _integrator,\n _referrer,\n _receiver,\n sendingAssetId,\n address(0),\n fromAmount,\n amountReceived\n );\n }\n\n /// @notice Performs a single swap from the network's native token to ERC20 token\n /// @param _transactionId the transaction id associated with the operation\n /// @param _integrator the name of the integrator\n /// @param _referrer the address of the referrer\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\n /// @param _minAmountOut the minimum amount of the final asset to receive\n /// @param _swapData an object containing swap related data to perform swaps before bridging\n function swapTokensSingleV3NativeToERC20(\n bytes32 _transactionId,\n string calldata _integrator,\n string calldata _referrer,\n address payable _receiver,\n uint256 _minAmountOut,\n LibSwap.SwapData calldata _swapData\n ) external payable {\n address callTo = _swapData.callTo;\n // ensure that contract (callTo) and function selector are whitelisted\n if (\n !(LibAllowList.contractIsAllowed(callTo) &&\n LibAllowList.selectorIsAllowed(bytes4(_swapData.callData[:4])))\n ) revert ContractCallNotAllowed();\n\n // execute swap\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = callTo.call{ value: msg.value }(\n _swapData.callData\n );\n if (!success) {\n LibUtil.revertWith(res);\n }\n\n _returnPositiveSlippageNative(_receiver);\n\n // get contract's balance (which will be sent in full to user)\n address receivingAssetId = _swapData.receivingAssetId;\n uint256 amountReceived = ERC20(receivingAssetId).balanceOf(\n address(this)\n );\n\n // ensure that minAmountOut was received\n if (amountReceived < _minAmountOut)\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\n\n // transfer funds to receiver\n ERC20(receivingAssetId).safeTransfer(_receiver, amountReceived);\n\n // emit events (both required for tracking)\n uint256 fromAmount = _swapData.fromAmount;\n emit LibSwap.AssetSwapped(\n _transactionId,\n callTo,\n address(0),\n receivingAssetId,\n fromAmount,\n amountReceived,\n block.timestamp\n );\n\n emit ILiFi.LiFiGenericSwapCompleted(\n _transactionId,\n _integrator,\n _referrer,\n _receiver,\n address(0),\n receivingAssetId,\n fromAmount,\n amountReceived\n );\n }\n\n // MULTIPLE SWAPS\n\n /// @notice Performs multiple swaps in one transaction, starting with ERC20 and ending with native\n /// @param _transactionId the transaction id associated with the operation\n /// @param _integrator the name of the integrator\n /// @param _referrer the address of the referrer\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\n /// @param _minAmountOut the minimum amount of the final asset to receive\n /// @param _swapData an object containing swap related data to perform swaps before bridging\n function swapTokensMultipleV3ERC20ToNative(\n bytes32 _transactionId,\n string calldata _integrator,\n string calldata _referrer,\n address payable _receiver,\n uint256 _minAmountOut,\n LibSwap.SwapData[] calldata _swapData\n ) external {\n _depositMultipleERC20Tokens(_swapData);\n _executeSwaps(_swapData, _transactionId, _receiver);\n _transferNativeTokensAndEmitEvent(\n _transactionId,\n _integrator,\n _referrer,\n _receiver,\n _minAmountOut,\n _swapData\n );\n }\n\n /// @notice Performs multiple swaps in one transaction, starting with ERC20 and ending with ERC20\n /// @param _transactionId the transaction id associated with the operation\n /// @param _integrator the name of the integrator\n /// @param _referrer the address of the referrer\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\n /// @param _minAmountOut the minimum amount of the final asset to receive\n /// @param _swapData an object containing swap related data to perform swaps before bridging\n function swapTokensMultipleV3ERC20ToERC20(\n bytes32 _transactionId,\n string calldata _integrator,\n string calldata _referrer,\n address payable _receiver,\n uint256 _minAmountOut,\n LibSwap.SwapData[] calldata _swapData\n ) external {\n _depositMultipleERC20Tokens(_swapData);\n _executeSwaps(_swapData, _transactionId, _receiver);\n _transferERC20TokensAndEmitEvent(\n _transactionId,\n _integrator,\n _referrer,\n _receiver,\n _minAmountOut,\n _swapData\n );\n }\n\n /// @notice Performs multiple swaps in one transaction, starting with native and ending with ERC20\n /// @param _transactionId the transaction id associated with the operation\n /// @param _integrator the name of the integrator\n /// @param _referrer the address of the referrer\n /// @param _receiver the address to receive the swapped tokens into (also excess tokens)\n /// @param _minAmountOut the minimum amount of the final asset to receive\n /// @param _swapData an object containing swap related data to perform swaps before bridging\n function swapTokensMultipleV3NativeToERC20(\n bytes32 _transactionId,\n string calldata _integrator,\n string calldata _referrer,\n address payable _receiver,\n uint256 _minAmountOut,\n LibSwap.SwapData[] calldata _swapData\n ) external payable {\n _executeSwaps(_swapData, _transactionId, _receiver);\n _transferERC20TokensAndEmitEvent(\n _transactionId,\n _integrator,\n _referrer,\n _receiver,\n _minAmountOut,\n _swapData\n );\n }\n\n /// Private helper methods ///\n function _depositMultipleERC20Tokens(\n LibSwap.SwapData[] calldata _swapData\n ) private {\n // initialize variables before loop to save gas\n uint256 numOfSwaps = _swapData.length;\n LibSwap.SwapData calldata currentSwap;\n\n // go through all swaps and deposit tokens, where required\n for (uint256 i = 0; i < numOfSwaps; ) {\n currentSwap = _swapData[i];\n if (currentSwap.requiresDeposit) {\n // we will not check msg.value as tx will fail anyway if not enough value available\n // thus we only deposit ERC20 tokens here\n ERC20(currentSwap.sendingAssetId).safeTransferFrom(\n msg.sender,\n address(this),\n currentSwap.fromAmount\n );\n }\n unchecked {\n ++i;\n }\n }\n }\n\n function _depositAndSwapERC20Single(\n LibSwap.SwapData calldata _swapData,\n address _receiver\n ) private {\n ERC20 sendingAsset = ERC20(_swapData.sendingAssetId);\n uint256 fromAmount = _swapData.fromAmount;\n // deposit funds\n sendingAsset.safeTransferFrom(msg.sender, address(this), fromAmount);\n\n // ensure that contract (callTo) and function selector are whitelisted\n address callTo = _swapData.callTo;\n address approveTo = _swapData.approveTo;\n bytes calldata callData = _swapData.callData;\n if (\n !(LibAllowList.contractIsAllowed(callTo) &&\n LibAllowList.selectorIsAllowed(bytes4(callData[:4])))\n ) revert ContractCallNotAllowed();\n\n // ensure that approveTo address is also whitelisted if it differs from callTo\n if (approveTo != callTo && !LibAllowList.contractIsAllowed(approveTo))\n revert ContractCallNotAllowed();\n\n // check if the current allowance is sufficient\n uint256 currentAllowance = sendingAsset.allowance(\n address(this),\n approveTo\n );\n\n // check if existing allowance is sufficient\n if (currentAllowance < fromAmount) {\n // check if is non-zero, set to 0 if not\n if (currentAllowance != 0) sendingAsset.safeApprove(approveTo, 0);\n // set allowance to uint max to avoid future approvals\n sendingAsset.safeApprove(approveTo, type(uint256).max);\n }\n\n // execute swap\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = callTo.call(callData);\n if (!success) {\n LibUtil.revertWith(res);\n }\n\n _returnPositiveSlippageERC20(sendingAsset, _receiver);\n }\n\n // @dev: this function will not work with swapData that has multiple swaps with the same sendingAssetId\n // as the _returnPositiveSlippage... functionality will refund all remaining tokens after the first swap\n // We accept this fact since the use case is not common yet. As an alternative you can always use the\n // \"swapTokensGeneric\" function of the original GenericSwapFacet\n function _executeSwaps(\n LibSwap.SwapData[] calldata _swapData,\n bytes32 _transactionId,\n address _receiver\n ) private {\n // initialize variables before loop to save gas\n uint256 numOfSwaps = _swapData.length;\n ERC20 sendingAsset;\n address sendingAssetId;\n address receivingAssetId;\n LibSwap.SwapData calldata currentSwap;\n bool success;\n bytes memory returnData;\n uint256 currentAllowance;\n\n // go through all swaps\n for (uint256 i = 0; i < numOfSwaps; ) {\n currentSwap = _swapData[i];\n sendingAssetId = currentSwap.sendingAssetId;\n sendingAsset = ERC20(currentSwap.sendingAssetId);\n receivingAssetId = currentSwap.receivingAssetId;\n\n // check if callTo address is whitelisted\n if (\n !LibAllowList.contractIsAllowed(currentSwap.callTo) ||\n !LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n )\n ) {\n revert ContractCallNotAllowed();\n }\n\n // if approveTo address is different to callTo, check if it's whitelisted, too\n if (\n currentSwap.approveTo != currentSwap.callTo &&\n !LibAllowList.contractIsAllowed(currentSwap.approveTo)\n ) {\n revert ContractCallNotAllowed();\n }\n\n if (LibAsset.isNativeAsset(sendingAssetId)) {\n // Native\n // execute the swap\n (success, returnData) = currentSwap.callTo.call{\n value: currentSwap.fromAmount\n }(currentSwap.callData);\n if (!success) {\n LibUtil.revertWith(returnData);\n }\n\n // return any potential leftover sendingAsset tokens\n // but only for swaps, not for fee collections (otherwise the whole amount would be returned before the actual swap)\n if (sendingAssetId != receivingAssetId)\n _returnPositiveSlippageNative(_receiver);\n } else {\n // ERC20\n // check if the current allowance is sufficient\n currentAllowance = sendingAsset.allowance(\n address(this),\n currentSwap.approveTo\n );\n if (currentAllowance < currentSwap.fromAmount) {\n sendingAsset.safeApprove(currentSwap.approveTo, 0);\n sendingAsset.safeApprove(\n currentSwap.approveTo,\n type(uint256).max\n );\n }\n\n // execute the swap\n (success, returnData) = currentSwap.callTo.call(\n currentSwap.callData\n );\n if (!success) {\n LibUtil.revertWith(returnData);\n }\n\n // return any potential leftover sendingAsset tokens\n // but only for swaps, not for fee collections (otherwise the whole amount would be returned before the actual swap)\n if (sendingAssetId != receivingAssetId)\n _returnPositiveSlippageERC20(sendingAsset, _receiver);\n }\n\n // emit AssetSwapped event\n // @dev: this event might in some cases emit inaccurate information. e.g. if a token is swapped and this contract already held a balance of the receivingAsset\n // then the event will show swapOutputAmount + existingBalance as toAmount. We accept this potential inaccuracy in return for gas savings and may update this\n // at a later stage when the described use case becomes more common\n emit LibSwap.AssetSwapped(\n _transactionId,\n currentSwap.callTo,\n sendingAssetId,\n receivingAssetId,\n currentSwap.fromAmount,\n LibAsset.isNativeAsset(receivingAssetId)\n ? address(this).balance\n : ERC20(receivingAssetId).balanceOf(address(this)),\n block.timestamp\n );\n\n unchecked {\n ++i;\n }\n }\n }\n\n function _transferERC20TokensAndEmitEvent(\n bytes32 _transactionId,\n string calldata _integrator,\n string calldata _referrer,\n address payable _receiver,\n uint256 _minAmountOut,\n LibSwap.SwapData[] calldata _swapData\n ) private {\n // determine the end result of the swap\n address finalAssetId = _swapData[_swapData.length - 1]\n .receivingAssetId;\n uint256 amountReceived = ERC20(finalAssetId).balanceOf(address(this));\n\n // make sure minAmountOut was received\n if (amountReceived < _minAmountOut)\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\n\n // transfer to receiver\n ERC20(finalAssetId).safeTransfer(_receiver, amountReceived);\n\n // emit event\n emit ILiFi.LiFiGenericSwapCompleted(\n _transactionId,\n _integrator,\n _referrer,\n _receiver,\n _swapData[0].sendingAssetId,\n finalAssetId,\n _swapData[0].fromAmount,\n amountReceived\n );\n }\n\n function _transferNativeTokensAndEmitEvent(\n bytes32 _transactionId,\n string calldata _integrator,\n string calldata _referrer,\n address payable _receiver,\n uint256 _minAmountOut,\n LibSwap.SwapData[] calldata _swapData\n ) private {\n console2.log(\"in _transferNativeTokensAndEmitEvent\");\n uint256 amountReceived = address(this).balance;\n\n // make sure minAmountOut was received\n if (amountReceived < _minAmountOut)\n revert CumulativeSlippageTooHigh(_minAmountOut, amountReceived);\n\n // transfer funds to receiver\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = _receiver.call{ value: amountReceived }(\"\");\n if (!success) {\n console2.log(\"HEYA\");\n revert NativeAssetTransferFailed();\n }\n\n // emit event\n emit ILiFi.LiFiGenericSwapCompleted(\n _transactionId,\n _integrator,\n _referrer,\n _receiver,\n _swapData[0].sendingAssetId,\n address(0),\n _swapData[0].fromAmount,\n amountReceived\n );\n }\n\n // returns any unused 'sendingAsset' tokens (=> positive slippage) to the receiver address\n function _returnPositiveSlippageERC20(\n ERC20 sendingAsset,\n address receiver\n ) private {\n // if a balance exists in sendingAsset, it must be positive slippage\n if (address(sendingAsset) != address(0)) {\n uint256 sendingAssetBalance = sendingAsset.balanceOf(\n address(this)\n );\n\n if (sendingAssetBalance > 0) {\n sendingAsset.safeTransfer(receiver, sendingAssetBalance);\n }\n }\n }\n\n // returns any unused native tokens (=> positive slippage) to the receiver address\n function _returnPositiveSlippageNative(address receiver) private {\n // if a native balance exists in sendingAsset, it must be positive slippage\n uint256 nativeBalance = address(this).balance;\n\n if (nativeBalance > 0) {\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = receiver.call{ value: nativeBalance }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n\n function revertWith(bytes memory data) internal pure {\n assembly {\n let dataSize := mload(data) // Load the size of the data\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\n revert(dataPtr, dataSize) // Revert with the given data\n }\n }\n}\n" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n LibUtil.revertWith(res);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/solmate/src/utils/SafeTransferLib.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20} from \"../tokens/ERC20.sol\";\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n /*//////////////////////////////////////////////////////////////\n ETH OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferETH(address to, uint256 amount) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Transfer the ETH and store if it succeeded or not.\n success := call(gas(), to, amount, 0, 0, 0, 0)\n }\n\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferFrom(\n ERC20 token,\n address from,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), from) // Append the \"from\" argument.\n mstore(add(freeMemoryPointer, 36), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 68), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FROM_FAILED\");\n }\n\n function safeTransfer(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FAILED\");\n }\n\n function safeApprove(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"APPROVE_FAILED\");\n }\n}\n" + }, + "lib/forge-std/src/console2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\n/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should\n/// use `int256` and `uint256`. This modified version fixes that. This version is recommended\n/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in\n/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.\n/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178\nlibrary console2 {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _castLogPayloadViewToPure(\n function(bytes memory) internal view fnIn\n ) internal pure returns (function(bytes memory) internal pure fnOut) {\n assembly {\n fnOut := fnIn\n }\n }\n\n function _sendLogPayload(bytes memory payload) internal pure {\n _castLogPayloadViewToPure(_sendLogPayloadView)(payload);\n }\n\n function _sendLogPayloadView(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function logUint(uint256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function logString(string memory p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function log(int256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function log(string memory p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint256 p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256)\", p0, p1));\n }\n\n function log(uint256 p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string)\", p0, p1));\n }\n\n function log(uint256 p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool)\", p0, p1));\n }\n\n function log(uint256 p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address)\", p0, p1));\n }\n\n function log(string memory p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n }\n\n function log(string memory p0, int256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,int256)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + }, + "lib/openzeppelin-contracts/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" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\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 ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \AmarokFacetPacked +0xf18a285f4e6f720eb9b4e05df71f88b9552e6adb +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/AmarokFacetPacked.sol\": {\r\n \"content\": \"// // SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IConnextHandler } from \\\"../Interfaces/IConnextHandler.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { ERC20, SafeTransferLib } from \\\"solmate/utils/SafeTransferLib.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { TransferrableOwnership } from \\\"../Helpers/TransferrableOwnership.sol\\\";\\nimport { AmarokFacet } from \\\"lifi/Facets/AmarokFacet.sol\\\";\\nimport { console2 } from \\\"forge-std/console2.sol\\\";\\n\\n/// @title AmarokFacetPacked\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Amarok in a gas-optimized way\\n/// @custom:version 1.0.0\\ncontract AmarokFacetPacked is ILiFi, TransferrableOwnership {\\n using SafeTransferLib for ERC20;\\n\\n /// Storage\\n\\n /// @notice The contract address of the connext handler on the source chain.\\n IConnextHandler private immutable connextHandler;\\n\\n /// Events ///\\n\\n event LiFiAmarokTransfer(bytes8 _transactionId);\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _connextHandler The contract address of the connext handler on the source chain.\\n /// @param _owner The contract owner to approve tokens.\\n constructor(\\n IConnextHandler _connextHandler,\\n address _owner\\n ) TransferrableOwnership(_owner) {\\n connextHandler = _connextHandler;\\n }\\n\\n /// External Methods ///\\n\\n /// @dev Only meant to be called outside of the context of the diamond\\n /// @notice Sets approval for the Amarok bridge to spend the specified token\\n /// @param tokensToApprove The tokens to approve to approve to the Amarok bridge\\n function setApprovalForBridge(\\n address[] calldata tokensToApprove\\n ) external onlyOwner {\\n uint256 numTokens = tokensToApprove.length;\\n\\n for (uint256 i; i < numTokens; i++) {\\n // Give Amarok approval to bridge tokens\\n LibAsset.maxApproveERC20(\\n IERC20(tokensToApprove[i]),\\n address(connextHandler),\\n type(uint256).max\\n );\\n }\\n }\\n\\n /// @notice Bridges ERC20 tokens via Amarok\\n /// No params, all data will be extracted from manually encoded callData\\n function startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset() external {\\n // extract parameters that are used multiple times in this function\\n address sendingAssetId = address(bytes20(msg.data[32:52]));\\n uint256 minAmount = uint256(uint128(bytes16(msg.data[52:68])));\\n address receiver = address(bytes20(msg.data[12:32]));\\n uint256 relayerFee = uint64(uint32(bytes4(msg.data[76:92])));\\n\\n // Deposit assets\\n ERC20(sendingAssetId).safeTransferFrom(\\n msg.sender,\\n address(this),\\n minAmount\\n );\\n\\n // call Amarok bridge\\n connextHandler.xcall(\\n uint32(bytes4(msg.data[68:72])), // _destChainDomainId\\n receiver, // _to\\n sendingAssetId,\\n receiver, // _delegate\\n minAmount - relayerFee,\\n uint256(uint128(uint64(uint32(bytes4(msg.data[72:76]))))), // slippageTol\\n \\\"\\\", // calldata (not required)\\n relayerFee\\n );\\n\\n emit LiFiAmarokTransfer(bytes8(msg.data[4:12]));\\n }\\n\\n function startBridgeTokensViaAmarokERC20PackedPayFeeWithNative()\\n external\\n payable\\n {\\n // extract parameters that are used multiple times in this function\\n address sendingAssetId = address(bytes20(msg.data[32:52]));\\n uint256 minAmount = uint256(uint128(bytes16(msg.data[52:68])));\\n address receiver = address(bytes20(msg.data[12:32]));\\n\\n // Deposit assets\\n ERC20(sendingAssetId).safeTransferFrom(\\n msg.sender,\\n address(this),\\n minAmount\\n );\\n\\n // call Amarok bridge\\n connextHandler.xcall{ value: msg.value }(\\n uint32(bytes4(msg.data[68:72])), // destChainDomainId\\n receiver, // _to\\n sendingAssetId,\\n receiver, // _delegate\\n minAmount,\\n uint256(uint128(uint64(uint32(bytes4(msg.data[72:76]))))), // slippageTol\\n \\\"\\\" // calldata (not required)\\n );\\n\\n emit LiFiAmarokTransfer(bytes8(msg.data[4:12]));\\n }\\n\\n /// @notice Bridges ERC20 tokens via Amarok\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param sendingAssetId Address of the source asset to bridge\\n /// @param minAmount Amount of the source asset to bridge\\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\\n /// @param slippageTol Maximum acceptable slippage in BPS. For example, a value of 30 means 0.3% slippage\\n /// @param relayerFee The amount of relayer fee the tx called xcall with\\n function startBridgeTokensViaAmarokERC20MinPayFeeWithAsset(\\n bytes32 transactionId,\\n address receiver,\\n address sendingAssetId,\\n uint256 minAmount,\\n uint32 destChainDomainId,\\n uint256 slippageTol,\\n uint256 relayerFee\\n ) external {\\n // Deposit assets\\n ERC20(sendingAssetId).safeTransferFrom(\\n msg.sender,\\n address(this),\\n minAmount\\n );\\n\\n // Bridge assets\\n connextHandler.xcall(\\n destChainDomainId,\\n receiver, // _to\\n sendingAssetId,\\n receiver, // _delegate\\n minAmount - relayerFee,\\n slippageTol,\\n \\\"\\\", // calldata (not required)\\n relayerFee\\n );\\n\\n emit LiFiAmarokTransfer(bytes8(transactionId));\\n }\\n\\n /// @notice Bridges ERC20 tokens via Amarok\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param sendingAssetId Address of the source asset to bridge\\n /// @param minAmount Amount of the source asset to bridge\\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\\n /// @param slippageTol Maximum acceptable slippage in BPS. For example, a value of 30 means 0.3% slippage\\n function startBridgeTokensViaAmarokERC20MinPayFeeWithNative(\\n bytes32 transactionId,\\n address receiver,\\n address sendingAssetId,\\n uint256 minAmount,\\n uint32 destChainDomainId,\\n uint256 slippageTol\\n ) external payable {\\n // Deposit assets\\n ERC20(sendingAssetId).safeTransferFrom(\\n msg.sender,\\n address(this),\\n minAmount\\n );\\n\\n // Bridge assets\\n connextHandler.xcall{ value: msg.value }(\\n destChainDomainId,\\n receiver, // _to\\n sendingAssetId,\\n receiver, // _delegate\\n minAmount,\\n slippageTol,\\n \\\"\\\" // calldata (not required)\\n );\\n\\n emit LiFiAmarokTransfer(bytes8(transactionId));\\n }\\n\\n /// @notice Encode call data to bridge ERC20 tokens via Amarok\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param sendingAssetId Address of the source asset to bridge\\n /// @param minAmount Amount of the source asset to bridge\\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\\n /// @param slippageTol Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)\\n /// @param relayerFee The amount of relayer fee the tx called xcall with\\n function encode_startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset(\\n bytes32 transactionId,\\n address receiver,\\n address sendingAssetId,\\n uint256 minAmount,\\n uint32 destChainDomainId,\\n uint256 slippageTol,\\n uint256 relayerFee\\n ) external pure returns (bytes memory) {\\n require(\\n minAmount <= type(uint128).max,\\n \\\"minAmount value passed too big to fit in uint128\\\"\\n );\\n require(\\n slippageTol <= type(uint32).max,\\n \\\"slippageTol value passed too big to fit in uint32\\\"\\n );\\n require(\\n relayerFee <= type(uint128).max,\\n \\\"relayerFee value passed too big to fit in uint128\\\"\\n );\\n\\n return\\n bytes.concat(\\n AmarokFacetPacked\\n .startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset\\n .selector,\\n bytes8(transactionId), // we only use 8 bytes of the 32bytes txId in order to save gas\\n bytes20(receiver),\\n bytes20(sendingAssetId),\\n bytes16(uint128(minAmount)),\\n bytes4(destChainDomainId),\\n bytes4(uint32(slippageTol)),\\n bytes16(uint128(relayerFee))\\n );\\n }\\n\\n /// @notice Encode call data to bridge ERC20 tokens via Amarok\\n /// @param transactionId Custom transaction ID for tracking\\n /// @param receiver Receiving wallet address\\n /// @param sendingAssetId Address of the source asset to bridge\\n /// @param minAmount Amount of the source asset to bridge\\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\\n /// @param slippageTol Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)\\n function encode_startBridgeTokensViaAmarokERC20PackedPayFeeWithNative(\\n bytes32 transactionId,\\n address receiver,\\n address sendingAssetId,\\n uint256 minAmount,\\n uint32 destChainDomainId,\\n uint256 slippageTol\\n ) external pure returns (bytes memory) {\\n require(\\n minAmount <= type(uint128).max,\\n \\\"minAmount value passed too big to fit in uint128\\\"\\n );\\n require(\\n slippageTol <= type(uint32).max,\\n \\\"slippageTol value passed too big to fit in uint32\\\"\\n );\\n\\n return\\n bytes.concat(\\n AmarokFacetPacked\\n .startBridgeTokensViaAmarokERC20PackedPayFeeWithNative\\n .selector,\\n bytes8(transactionId), // we only use 8 bytes of the 32bytes txId in order to save gas\\n bytes20(receiver),\\n bytes20(sendingAssetId),\\n bytes16(uint128(minAmount)),\\n bytes4(destChainDomainId),\\n bytes4(uint32(slippageTol))\\n );\\n }\\n\\n /// @notice Decodes calldata for startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset\\n /// @param _data the calldata to decode\\n function decode_startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset(\\n bytes calldata _data\\n )\\n external\\n pure\\n returns (BridgeData memory, AmarokFacet.AmarokData memory)\\n {\\n require(\\n _data.length >= 92,\\n \\\"data passed in is not the correct length\\\"\\n );\\n\\n BridgeData memory bridgeData;\\n AmarokFacet.AmarokData memory amarokData;\\n\\n uint32 destChainDomainId = uint32(bytes4(_data[68:72]));\\n\\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\\n bridgeData.receiver = address(bytes20(_data[12:32]));\\n bridgeData.destinationChainId = getChainIdForDomain(destChainDomainId);\\n bridgeData.sendingAssetId = address(bytes20(_data[32:52]));\\n bridgeData.minAmount = uint256(uint128(bytes16(_data[52:68])));\\n\\n amarokData.callData = \\\"\\\";\\n amarokData.callTo = bridgeData.receiver;\\n amarokData.destChainDomainId = destChainDomainId;\\n amarokData.slippageTol = uint32(bytes4(_data[72:76]));\\n amarokData.relayerFee = uint256(uint128(bytes16(_data[76:92])));\\n amarokData.delegate = bridgeData.receiver;\\n amarokData.payFeeWithSendingAsset = true;\\n\\n return (bridgeData, amarokData);\\n }\\n\\n /// @notice Decodes calldata for startBridgeTokensViaAmarokERC20PackedPayFeeWithNative\\n /// @param _data the calldata to decode\\n function decode_startBridgeTokensViaAmarokERC20PackedPayFeeWithNative(\\n bytes calldata _data\\n )\\n external\\n pure\\n returns (BridgeData memory, AmarokFacet.AmarokData memory)\\n {\\n require(\\n _data.length >= 76,\\n \\\"data passed in is not the correct length\\\"\\n );\\n\\n BridgeData memory bridgeData;\\n AmarokFacet.AmarokData memory amarokData;\\n\\n uint32 destChainDomainId = uint32(bytes4(_data[68:72]));\\n\\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\\n bridgeData.receiver = address(bytes20(_data[12:32]));\\n bridgeData.destinationChainId = getChainIdForDomain(destChainDomainId);\\n bridgeData.sendingAssetId = address(bytes20(_data[32:52]));\\n bridgeData.minAmount = uint256(uint128(bytes16(_data[52:68])));\\n\\n amarokData.callData = \\\"\\\";\\n amarokData.callTo = bridgeData.receiver;\\n amarokData.destChainDomainId = destChainDomainId;\\n amarokData.slippageTol = uint256(\\n uint128(uint32(bytes4(_data[72:76])))\\n );\\n amarokData.delegate = bridgeData.receiver;\\n amarokData.payFeeWithSendingAsset = false;\\n\\n return (bridgeData, amarokData);\\n }\\n\\n function getChainIdForDomain(\\n uint32 domainId\\n ) public pure returns (uint32 chainId) {\\n if (domainId == 6648936) return 1;\\n // ETH\\n else if (domainId == 1886350457) return 137;\\n // POL\\n else if (domainId == 6450786) return 56;\\n // BSC\\n else if (domainId == 1869640809) return 10;\\n // OPT\\n else if (domainId == 6778479) return 100;\\n // GNO/DAI\\n else if (domainId == 1634886255) return 42161;\\n // ARB\\n else if (domainId == 1818848877) return 59144; // LIN\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IConnextHandler.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IConnextHandler {\\n /// @notice These are the call parameters that will remain constant between the\\n /// two chains. They are supplied on `xcall` and should be asserted on `execute`\\n /// @property to - The account that receives funds, in the event of a crosschain call,\\n /// will receive funds if the call fails.\\n /// @param to - The address you are sending funds (and potentially data) to\\n /// @param callData - The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.\\n /// @param originDomain - The originating domain (i.e. where `xcall` is called). Must match nomad domain schema\\n /// @param destinationDomain - The final domain (i.e. where `execute` / `reconcile` are called). Must match nomad domain schema\\n /// @param agent - An address who can execute txs on behalf of `to`, in addition to allowing relayers\\n /// @param recovery - The address to send funds to if your `Executor.execute call` fails\\n /// @param forceSlow - If true, will take slow liquidity path even if it is not a permissioned call\\n /// @param receiveLocal - If true, will use the local nomad asset on the destination instead of adopted.\\n /// @param callback - The address on the origin domain of the callback contract\\n /// @param callbackFee - The relayer fee to execute the callback\\n /// @param relayerFee - The amount of relayer fee the tx called xcall with\\n /// @param slippageTol - Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)\\n struct CallParams {\\n address to;\\n bytes callData;\\n uint32 originDomain;\\n uint32 destinationDomain;\\n address agent;\\n address recovery;\\n bool forceSlow;\\n bool receiveLocal;\\n address callback;\\n uint256 callbackFee;\\n uint256 relayerFee;\\n uint256 slippageTol;\\n }\\n\\n /// @notice The arguments you supply to the `xcall` function called by user on origin domain\\n /// @param params - The CallParams. These are consistent across sending and receiving chains\\n /// @param transactingAsset - The asset the caller sent with the transfer. Can be the adopted, canonical,\\n /// or the representational asset\\n /// @param transactingAmount - The amount of transferring asset supplied by the user in the `xcall`\\n /// @param originMinOut - Minimum amount received on swaps for adopted <> local on origin chain\\n struct XCallArgs {\\n CallParams params;\\n address transactingAsset; // Could be adopted, local, or wrapped\\n uint256 transactingAmount;\\n uint256 originMinOut;\\n }\\n\\n function xcall(\\n uint32 destination,\\n address recipient,\\n address tokenAddress,\\n address delegate,\\n uint256 amount,\\n uint256 slippage,\\n bytes memory callData\\n ) external payable returns (bytes32);\\n\\n function xcall(\\n uint32 destination,\\n address recipient,\\n address tokenAddress,\\n address delegate,\\n uint256 amount,\\n uint256 slippage,\\n bytes memory callData,\\n uint256 _relayerFee\\n ) external returns (bytes32);\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"lib/solmate/src/utils/SafeTransferLib.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\nimport {ERC20} from \\\"../tokens/ERC20.sol\\\";\\n\\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\\nlibrary SafeTransferLib {\\n /*//////////////////////////////////////////////////////////////\\n ETH OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferETH(address to, uint256 amount) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Transfer the ETH and store if it succeeded or not.\\n success := call(gas(), to, amount, 0, 0, 0, 0)\\n }\\n\\n require(success, \\\"ETH_TRANSFER_FAILED\\\");\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferFrom(\\n ERC20 token,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), from) // Append the \\\"from\\\" argument.\\n mstore(add(freeMemoryPointer, 36), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 68), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FROM_FAILED\\\");\\n }\\n\\n function safeTransfer(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FAILED\\\");\\n }\\n\\n function safeApprove(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"APPROVE_FAILED\\\");\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/TransferrableOwnership.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IERC173 } from \\\"../Interfaces/IERC173.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\n\\ncontract TransferrableOwnership is IERC173 {\\n address public owner;\\n address public pendingOwner;\\n\\n /// Errors ///\\n error UnAuthorized();\\n error NoNullOwner();\\n error NewOwnerMustNotBeSelf();\\n error NoPendingOwnershipTransfer();\\n error NotPendingOwner();\\n\\n /// Events ///\\n event OwnershipTransferRequested(\\n address indexed _from,\\n address indexed _to\\n );\\n\\n constructor(address initialOwner) {\\n owner = initialOwner;\\n }\\n\\n modifier onlyOwner() {\\n if (msg.sender != owner) revert UnAuthorized();\\n _;\\n }\\n\\n /// @notice Initiates transfer of ownership to a new address\\n /// @param _newOwner the address to transfer ownership to\\n function transferOwnership(address _newOwner) external onlyOwner {\\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\\n pendingOwner = _newOwner;\\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\\n }\\n\\n /// @notice Cancel transfer of ownership\\n function cancelOwnershipTransfer() external onlyOwner {\\n if (pendingOwner == LibAsset.NULL_ADDRESS)\\n revert NoPendingOwnershipTransfer();\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n\\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\\n function confirmOwnershipTransfer() external {\\n address _pendingOwner = pendingOwner;\\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\\n emit OwnershipTransferred(owner, _pendingOwner);\\n owner = _pendingOwner;\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n}\\n\"\r\n },\r\n \"src/Facets/AmarokFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IConnextHandler } from \\\"../Interfaces/IConnextHandler.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { InformationMismatch } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title Amarok Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Connext Amarok\\n/// @custom:version 2.0.0\\ncontract AmarokFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n /// @notice The contract address of the connext handler on the source chain.\\n IConnextHandler private immutable connextHandler;\\n\\n /// @param callData The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.\\n /// @param callTo The address of the contract on dest chain that will receive bridged funds and execute data\\n /// @param relayerFee The amount of relayer fee the tx called xcall with\\n /// @param slippageTol Maximum acceptable slippage in BPS. For example, a value of 30 means 0.3% slippage\\n /// @param delegate Destination delegate address\\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\\n /// @param payFeeWithSendingAsset Whether to pay the relayer fee with the sending asset or not\\n struct AmarokData {\\n bytes callData;\\n address callTo;\\n uint256 relayerFee;\\n uint256 slippageTol;\\n address delegate;\\n uint32 destChainDomainId;\\n bool payFeeWithSendingAsset;\\n }\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _connextHandler The contract address of the connext handler on the source chain.\\n constructor(IConnextHandler _connextHandler) {\\n connextHandler = _connextHandler;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Amarok\\n /// @param _bridgeData Data containing core information for bridging\\n /// @param _amarokData Data specific to bridge\\n function startBridgeTokensViaAmarok(\\n BridgeData calldata _bridgeData,\\n AmarokData calldata _amarokData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n noNativeAsset(_bridgeData)\\n {\\n validateDestinationCallFlag(_bridgeData, _amarokData);\\n\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n\\n _startBridge(_bridgeData, _amarokData);\\n }\\n\\n /// @notice Performs a swap before bridging via Amarok\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _amarokData Data specific to Amarok\\n function swapAndStartBridgeTokensViaAmarok(\\n BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n AmarokData calldata _amarokData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n noNativeAsset(_bridgeData)\\n {\\n validateDestinationCallFlag(_bridgeData, _amarokData);\\n\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n _amarokData.relayerFee\\n );\\n\\n _startBridge(_bridgeData, _amarokData);\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Amarok\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _amarokData Data specific to Amarok\\n function _startBridge(\\n BridgeData memory _bridgeData,\\n AmarokData calldata _amarokData\\n ) private {\\n // give max approval for token to Amarok bridge, if not already\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(connextHandler),\\n _bridgeData.minAmount\\n );\\n\\n // initiate bridge transaction\\n if (_amarokData.payFeeWithSendingAsset) {\\n connextHandler.xcall(\\n _amarokData.destChainDomainId,\\n _amarokData.callTo,\\n _bridgeData.sendingAssetId,\\n _amarokData.delegate,\\n _bridgeData.minAmount - _amarokData.relayerFee,\\n _amarokData.slippageTol,\\n _amarokData.callData,\\n _amarokData.relayerFee\\n );\\n } else {\\n connextHandler.xcall{ value: _amarokData.relayerFee }(\\n _amarokData.destChainDomainId,\\n _amarokData.callTo,\\n _bridgeData.sendingAssetId,\\n _amarokData.delegate,\\n _bridgeData.minAmount,\\n _amarokData.slippageTol,\\n _amarokData.callData\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n function validateDestinationCallFlag(\\n ILiFi.BridgeData memory _bridgeData,\\n AmarokData calldata _amarokData\\n ) private pure {\\n if (\\n (_amarokData.callData.length > 0) != _bridgeData.hasDestinationCall\\n ) {\\n revert InformationMismatch();\\n }\\n }\\n}\\n\"\r\n },\r\n \"lib/forge-std/src/console2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity >=0.4.22 <0.9.0;\\n\\n/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should\\n/// use `int256` and `uint256`. This modified version fixes that. This version is recommended\\n/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in\\n/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.\\n/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178\\nlibrary console2 {\\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\\n\\n function _castLogPayloadViewToPure(\\n function(bytes memory) internal view fnIn\\n ) internal pure returns (function(bytes memory) internal pure fnOut) {\\n assembly {\\n fnOut := fnIn\\n }\\n }\\n\\n function _sendLogPayload(bytes memory payload) internal pure {\\n _castLogPayloadViewToPure(_sendLogPayloadView)(payload);\\n }\\n\\n function _sendLogPayloadView(bytes memory payload) private view {\\n uint256 payloadLength = payload.length;\\n address consoleAddress = CONSOLE_ADDRESS;\\n /// @solidity memory-safe-assembly\\n assembly {\\n let payloadStart := add(payload, 32)\\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\\n }\\n }\\n\\n function log() internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log()\\\"));\\n }\\n\\n function logInt(int256 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(int256)\\\", p0));\\n }\\n\\n function logUint(uint256 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256)\\\", p0));\\n }\\n\\n function logString(string memory p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n }\\n\\n function logBool(bool p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n }\\n\\n function logAddress(address p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n }\\n\\n function logBytes(bytes memory p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes)\\\", p0));\\n }\\n\\n function logBytes1(bytes1 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes1)\\\", p0));\\n }\\n\\n function logBytes2(bytes2 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes2)\\\", p0));\\n }\\n\\n function logBytes3(bytes3 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes3)\\\", p0));\\n }\\n\\n function logBytes4(bytes4 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes4)\\\", p0));\\n }\\n\\n function logBytes5(bytes5 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes5)\\\", p0));\\n }\\n\\n function logBytes6(bytes6 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes6)\\\", p0));\\n }\\n\\n function logBytes7(bytes7 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes7)\\\", p0));\\n }\\n\\n function logBytes8(bytes8 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes8)\\\", p0));\\n }\\n\\n function logBytes9(bytes9 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes9)\\\", p0));\\n }\\n\\n function logBytes10(bytes10 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes10)\\\", p0));\\n }\\n\\n function logBytes11(bytes11 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes11)\\\", p0));\\n }\\n\\n function logBytes12(bytes12 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes12)\\\", p0));\\n }\\n\\n function logBytes13(bytes13 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes13)\\\", p0));\\n }\\n\\n function logBytes14(bytes14 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes14)\\\", p0));\\n }\\n\\n function logBytes15(bytes15 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes15)\\\", p0));\\n }\\n\\n function logBytes16(bytes16 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes16)\\\", p0));\\n }\\n\\n function logBytes17(bytes17 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes17)\\\", p0));\\n }\\n\\n function logBytes18(bytes18 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes18)\\\", p0));\\n }\\n\\n function logBytes19(bytes19 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes19)\\\", p0));\\n }\\n\\n function logBytes20(bytes20 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes20)\\\", p0));\\n }\\n\\n function logBytes21(bytes21 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes21)\\\", p0));\\n }\\n\\n function logBytes22(bytes22 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes22)\\\", p0));\\n }\\n\\n function logBytes23(bytes23 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes23)\\\", p0));\\n }\\n\\n function logBytes24(bytes24 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes24)\\\", p0));\\n }\\n\\n function logBytes25(bytes25 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes25)\\\", p0));\\n }\\n\\n function logBytes26(bytes26 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes26)\\\", p0));\\n }\\n\\n function logBytes27(bytes27 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes27)\\\", p0));\\n }\\n\\n function logBytes28(bytes28 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes28)\\\", p0));\\n }\\n\\n function logBytes29(bytes29 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes29)\\\", p0));\\n }\\n\\n function logBytes30(bytes30 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes30)\\\", p0));\\n }\\n\\n function logBytes31(bytes31 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes31)\\\", p0));\\n }\\n\\n function logBytes32(bytes32 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bytes32)\\\", p0));\\n }\\n\\n function log(uint256 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256)\\\", p0));\\n }\\n\\n function log(int256 p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(int256)\\\", p0));\\n }\\n\\n function log(string memory p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string)\\\", p0));\\n }\\n\\n function log(bool p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool)\\\", p0));\\n }\\n\\n function log(address p0) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address)\\\", p0));\\n }\\n\\n function log(uint256 p0, uint256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256)\\\", p0, p1));\\n }\\n\\n function log(uint256 p0, string memory p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string)\\\", p0, p1));\\n }\\n\\n function log(uint256 p0, bool p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool)\\\", p0, p1));\\n }\\n\\n function log(uint256 p0, address p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, uint256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, int256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,int256)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, string memory p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, bool p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool)\\\", p0, p1));\\n }\\n\\n function log(string memory p0, address p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address)\\\", p0, p1));\\n }\\n\\n function log(bool p0, uint256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256)\\\", p0, p1));\\n }\\n\\n function log(bool p0, string memory p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string)\\\", p0, p1));\\n }\\n\\n function log(bool p0, bool p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool)\\\", p0, p1));\\n }\\n\\n function log(bool p0, address p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address)\\\", p0, p1));\\n }\\n\\n function log(address p0, uint256 p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256)\\\", p0, p1));\\n }\\n\\n function log(address p0, string memory p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string)\\\", p0, p1));\\n }\\n\\n function log(address p0, bool p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool)\\\", p0, p1));\\n }\\n\\n function log(address p0, address p1) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address)\\\", p0, p1));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, bool p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, address p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, address p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, string memory p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, bool p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, bool p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, address p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, address p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(string memory p0, address p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, uint256 p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, string memory p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, string memory p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, bool p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, bool p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, bool p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, address p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, address p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, address p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(bool p0, address p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, uint256 p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, uint256 p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, string memory p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, string memory p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, string memory p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, bool p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, bool p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, bool p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, bool p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, address p1, uint256 p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, address p1, string memory p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, address p1, bool p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool)\\\", p0, p1, p2));\\n }\\n\\n function log(address p0, address p1, address p2) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address)\\\", p0, p1, p2));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,uint256,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, string memory p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,string,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, bool p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,bool,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(uint256 p0, address p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(uint256,address,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, uint256 p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,uint256,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, string memory p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,string,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, bool p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,bool,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(string memory p0, address p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(string,address,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, uint256 p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,uint256,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, string memory p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,string,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, bool p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,bool,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(bool p0, address p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(bool,address,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, uint256 p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,uint256,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, string memory p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,string,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, bool p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,bool,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, uint256 p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, uint256 p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, uint256 p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,uint256,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, string memory p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, string memory p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, string memory p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, string memory p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,string,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, bool p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, bool p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, bool p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, bool p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,bool,address)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, address p2, uint256 p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,uint256)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, address p2, string memory p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,string)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, address p2, bool p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,bool)\\\", p0, p1, p2, p3));\\n }\\n\\n function log(address p0, address p1, address p2, address p3) internal pure {\\n _sendLogPayload(abi.encodeWithSignature(\\\"log(address,address,address,address)\\\", p0, p1, p2, p3));\\n }\\n\\n}\"\r\n },\r\n \"lib/solmate/src/tokens/ERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\\nabstract contract ERC20 {\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /*//////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string public name;\\n\\n string public symbol;\\n\\n uint8 public immutable decimals;\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 public totalSupply;\\n\\n mapping(address => uint256) public balanceOf;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 internal immutable INITIAL_CHAIN_ID;\\n\\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\\n\\n mapping(address => uint256) public nonces;\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n constructor(\\n string memory _name,\\n string memory _symbol,\\n uint8 _decimals\\n ) {\\n name = _name;\\n symbol = _symbol;\\n decimals = _decimals;\\n\\n INITIAL_CHAIN_ID = block.chainid;\\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function approve(address spender, uint256 amount) public virtual returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n\\n return true;\\n }\\n\\n function transfer(address to, uint256 amount) public virtual returns (bool) {\\n balanceOf[msg.sender] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(msg.sender, to, amount);\\n\\n return true;\\n }\\n\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual returns (bool) {\\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\\n\\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\\n\\n balanceOf[from] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n return true;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 LOGIC\\n //////////////////////////////////////////////////////////////*/\\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 ) public virtual {\\n require(deadline >= block.timestamp, \\\"PERMIT_DEADLINE_EXPIRED\\\");\\n\\n // Unchecked because the only math done is incrementing\\n // the owner's nonce which cannot realistically overflow.\\n unchecked {\\n address recoveredAddress = ecrecover(\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR(),\\n keccak256(\\n abi.encode(\\n keccak256(\\n \\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\"\\n ),\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n require(recoveredAddress != address(0) && recoveredAddress == owner, \\\"INVALID_SIGNER\\\");\\n\\n allowance[recoveredAddress][spender] = value;\\n }\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\\n }\\n\\n function computeDomainSeparator() internal view virtual returns (bytes32) {\\n return\\n keccak256(\\n abi.encode(\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"),\\n keccak256(bytes(name)),\\n keccak256(\\\"1\\\"),\\n block.chainid,\\n address(this)\\n )\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _mint(address to, uint256 amount) internal virtual {\\n totalSupply += amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(address(0), to, amount);\\n }\\n\\n function _burn(address from, uint256 amount) internal virtual {\\n balanceOf[from] -= amount;\\n\\n // Cannot underflow because a user's balance\\n // will never be larger than the total supply.\\n unchecked {\\n totalSupply -= amount;\\n }\\n\\n emit Transfer(from, address(0), amount);\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IERC173.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\n/// @title ERC-173 Contract Ownership Standard\\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\\n/* is ERC165 */\\ninterface IERC173 {\\n /// @dev This emits when ownership of a contract changes.\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n /// @notice Get the address of the owner\\n /// @return owner_ The address of the owner.\\n function owner() external view returns (address owner_);\\n\\n /// @notice Set the address of the new owner of the contract\\n /// @dev Set _newOwner to address(0) to renounce any ownership.\\n /// @param _newOwner The address of the new owner of the contract\\n function transferOwnership(address _newOwner) external;\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IConnextHandler\",\"name\":\"_connextHandler\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NewOwnerMustNotBeSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoNullOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoPendingOwnershipTransfer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotPendingOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnAuthorized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes8\",\"name\":\"_transactionId\",\"type\":\"bytes8\"}],\"name\":\"LiFiAmarokTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"cancelOwnershipTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"confirmOwnershipTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"decode_startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"slippageTol\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destChainDomainId\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"payFeeWithSendingAsset\",\"type\":\"bool\"}],\"internalType\":\"struct AmarokFacet.AmarokData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"decode_startBridgeTokensViaAmarokERC20PackedPayFeeWithNative\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"slippageTol\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destChainDomainId\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"payFeeWithSendingAsset\",\"type\":\"bool\"}],\"internalType\":\"struct AmarokFacet.AmarokData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"destChainDomainId\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"slippageTol\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"}],\"name\":\"encode_startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"destChainDomainId\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"slippageTol\",\"type\":\"uint256\"}],\"name\":\"encode_startBridgeTokensViaAmarokERC20PackedPayFeeWithNative\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"domainId\",\"type\":\"uint32\"}],\"name\":\"getChainIdForDomain\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"chainId\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokensToApprove\",\"type\":\"address[]\"}],\"name\":\"setApprovalForBridge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"destChainDomainId\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"slippageTol\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"relayerFee\",\"type\":\"uint256\"}],\"name\":\"startBridgeTokensViaAmarokERC20MinPayFeeWithAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"destChainDomainId\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"slippageTol\",\"type\":\"uint256\"}],\"name\":\"startBridgeTokensViaAmarokERC20MinPayFeeWithNative\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBridgeTokensViaAmarokERC20PackedPayFeeWithNative\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ContractName: "AmarokFacetPacked", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000008898b472c54c31894e3b9bb83cea802a5d0e63c600000000000000000000000011f1022ca6adef6400e5677528a80d49a069c00c", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/AmarokFacetPacked.sol": { + "content": "// // SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IConnextHandler } from \"../Interfaces/IConnextHandler.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { ERC20, SafeTransferLib } from \"solmate/utils/SafeTransferLib.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { TransferrableOwnership } from \"../Helpers/TransferrableOwnership.sol\";\nimport { AmarokFacet } from \"lifi/Facets/AmarokFacet.sol\";\nimport { console2 } from \"forge-std/console2.sol\";\n\n/// @title AmarokFacetPacked\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Amarok in a gas-optimized way\n/// @custom:version 1.0.0\ncontract AmarokFacetPacked is ILiFi, TransferrableOwnership {\n using SafeTransferLib for ERC20;\n\n /// Storage\n\n /// @notice The contract address of the connext handler on the source chain.\n IConnextHandler private immutable connextHandler;\n\n /// Events ///\n\n event LiFiAmarokTransfer(bytes8 _transactionId);\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _connextHandler The contract address of the connext handler on the source chain.\n /// @param _owner The contract owner to approve tokens.\n constructor(\n IConnextHandler _connextHandler,\n address _owner\n ) TransferrableOwnership(_owner) {\n connextHandler = _connextHandler;\n }\n\n /// External Methods ///\n\n /// @dev Only meant to be called outside of the context of the diamond\n /// @notice Sets approval for the Amarok bridge to spend the specified token\n /// @param tokensToApprove The tokens to approve to approve to the Amarok bridge\n function setApprovalForBridge(\n address[] calldata tokensToApprove\n ) external onlyOwner {\n uint256 numTokens = tokensToApprove.length;\n\n for (uint256 i; i < numTokens; i++) {\n // Give Amarok approval to bridge tokens\n LibAsset.maxApproveERC20(\n IERC20(tokensToApprove[i]),\n address(connextHandler),\n type(uint256).max\n );\n }\n }\n\n /// @notice Bridges ERC20 tokens via Amarok\n /// No params, all data will be extracted from manually encoded callData\n function startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset() external {\n // extract parameters that are used multiple times in this function\n address sendingAssetId = address(bytes20(msg.data[32:52]));\n uint256 minAmount = uint256(uint128(bytes16(msg.data[52:68])));\n address receiver = address(bytes20(msg.data[12:32]));\n uint256 relayerFee = uint64(uint32(bytes4(msg.data[76:92])));\n\n // Deposit assets\n ERC20(sendingAssetId).safeTransferFrom(\n msg.sender,\n address(this),\n minAmount\n );\n\n // call Amarok bridge\n connextHandler.xcall(\n uint32(bytes4(msg.data[68:72])), // _destChainDomainId\n receiver, // _to\n sendingAssetId,\n receiver, // _delegate\n minAmount - relayerFee,\n uint256(uint128(uint64(uint32(bytes4(msg.data[72:76]))))), // slippageTol\n \"\", // calldata (not required)\n relayerFee\n );\n\n emit LiFiAmarokTransfer(bytes8(msg.data[4:12]));\n }\n\n function startBridgeTokensViaAmarokERC20PackedPayFeeWithNative()\n external\n payable\n {\n // extract parameters that are used multiple times in this function\n address sendingAssetId = address(bytes20(msg.data[32:52]));\n uint256 minAmount = uint256(uint128(bytes16(msg.data[52:68])));\n address receiver = address(bytes20(msg.data[12:32]));\n\n // Deposit assets\n ERC20(sendingAssetId).safeTransferFrom(\n msg.sender,\n address(this),\n minAmount\n );\n\n // call Amarok bridge\n connextHandler.xcall{ value: msg.value }(\n uint32(bytes4(msg.data[68:72])), // destChainDomainId\n receiver, // _to\n sendingAssetId,\n receiver, // _delegate\n minAmount,\n uint256(uint128(uint64(uint32(bytes4(msg.data[72:76]))))), // slippageTol\n \"\" // calldata (not required)\n );\n\n emit LiFiAmarokTransfer(bytes8(msg.data[4:12]));\n }\n\n /// @notice Bridges ERC20 tokens via Amarok\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param sendingAssetId Address of the source asset to bridge\n /// @param minAmount Amount of the source asset to bridge\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\n /// @param slippageTol Maximum acceptable slippage in BPS. For example, a value of 30 means 0.3% slippage\n /// @param relayerFee The amount of relayer fee the tx called xcall with\n function startBridgeTokensViaAmarokERC20MinPayFeeWithAsset(\n bytes32 transactionId,\n address receiver,\n address sendingAssetId,\n uint256 minAmount,\n uint32 destChainDomainId,\n uint256 slippageTol,\n uint256 relayerFee\n ) external {\n // Deposit assets\n ERC20(sendingAssetId).safeTransferFrom(\n msg.sender,\n address(this),\n minAmount\n );\n\n // Bridge assets\n connextHandler.xcall(\n destChainDomainId,\n receiver, // _to\n sendingAssetId,\n receiver, // _delegate\n minAmount - relayerFee,\n slippageTol,\n \"\", // calldata (not required)\n relayerFee\n );\n\n emit LiFiAmarokTransfer(bytes8(transactionId));\n }\n\n /// @notice Bridges ERC20 tokens via Amarok\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param sendingAssetId Address of the source asset to bridge\n /// @param minAmount Amount of the source asset to bridge\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\n /// @param slippageTol Maximum acceptable slippage in BPS. For example, a value of 30 means 0.3% slippage\n function startBridgeTokensViaAmarokERC20MinPayFeeWithNative(\n bytes32 transactionId,\n address receiver,\n address sendingAssetId,\n uint256 minAmount,\n uint32 destChainDomainId,\n uint256 slippageTol\n ) external payable {\n // Deposit assets\n ERC20(sendingAssetId).safeTransferFrom(\n msg.sender,\n address(this),\n minAmount\n );\n\n // Bridge assets\n connextHandler.xcall{ value: msg.value }(\n destChainDomainId,\n receiver, // _to\n sendingAssetId,\n receiver, // _delegate\n minAmount,\n slippageTol,\n \"\" // calldata (not required)\n );\n\n emit LiFiAmarokTransfer(bytes8(transactionId));\n }\n\n /// @notice Encode call data to bridge ERC20 tokens via Amarok\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param sendingAssetId Address of the source asset to bridge\n /// @param minAmount Amount of the source asset to bridge\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\n /// @param slippageTol Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)\n /// @param relayerFee The amount of relayer fee the tx called xcall with\n function encode_startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset(\n bytes32 transactionId,\n address receiver,\n address sendingAssetId,\n uint256 minAmount,\n uint32 destChainDomainId,\n uint256 slippageTol,\n uint256 relayerFee\n ) external pure returns (bytes memory) {\n require(\n minAmount <= type(uint128).max,\n \"minAmount value passed too big to fit in uint128\"\n );\n require(\n slippageTol <= type(uint32).max,\n \"slippageTol value passed too big to fit in uint32\"\n );\n require(\n relayerFee <= type(uint128).max,\n \"relayerFee value passed too big to fit in uint128\"\n );\n\n return\n bytes.concat(\n AmarokFacetPacked\n .startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset\n .selector,\n bytes8(transactionId), // we only use 8 bytes of the 32bytes txId in order to save gas\n bytes20(receiver),\n bytes20(sendingAssetId),\n bytes16(uint128(minAmount)),\n bytes4(destChainDomainId),\n bytes4(uint32(slippageTol)),\n bytes16(uint128(relayerFee))\n );\n }\n\n /// @notice Encode call data to bridge ERC20 tokens via Amarok\n /// @param transactionId Custom transaction ID for tracking\n /// @param receiver Receiving wallet address\n /// @param sendingAssetId Address of the source asset to bridge\n /// @param minAmount Amount of the source asset to bridge\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\n /// @param slippageTol Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)\n function encode_startBridgeTokensViaAmarokERC20PackedPayFeeWithNative(\n bytes32 transactionId,\n address receiver,\n address sendingAssetId,\n uint256 minAmount,\n uint32 destChainDomainId,\n uint256 slippageTol\n ) external pure returns (bytes memory) {\n require(\n minAmount <= type(uint128).max,\n \"minAmount value passed too big to fit in uint128\"\n );\n require(\n slippageTol <= type(uint32).max,\n \"slippageTol value passed too big to fit in uint32\"\n );\n\n return\n bytes.concat(\n AmarokFacetPacked\n .startBridgeTokensViaAmarokERC20PackedPayFeeWithNative\n .selector,\n bytes8(transactionId), // we only use 8 bytes of the 32bytes txId in order to save gas\n bytes20(receiver),\n bytes20(sendingAssetId),\n bytes16(uint128(minAmount)),\n bytes4(destChainDomainId),\n bytes4(uint32(slippageTol))\n );\n }\n\n /// @notice Decodes calldata for startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset\n /// @param _data the calldata to decode\n function decode_startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset(\n bytes calldata _data\n )\n external\n pure\n returns (BridgeData memory, AmarokFacet.AmarokData memory)\n {\n require(\n _data.length >= 92,\n \"data passed in is not the correct length\"\n );\n\n BridgeData memory bridgeData;\n AmarokFacet.AmarokData memory amarokData;\n\n uint32 destChainDomainId = uint32(bytes4(_data[68:72]));\n\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\n bridgeData.receiver = address(bytes20(_data[12:32]));\n bridgeData.destinationChainId = getChainIdForDomain(destChainDomainId);\n bridgeData.sendingAssetId = address(bytes20(_data[32:52]));\n bridgeData.minAmount = uint256(uint128(bytes16(_data[52:68])));\n\n amarokData.callData = \"\";\n amarokData.callTo = bridgeData.receiver;\n amarokData.destChainDomainId = destChainDomainId;\n amarokData.slippageTol = uint32(bytes4(_data[72:76]));\n amarokData.relayerFee = uint256(uint128(bytes16(_data[76:92])));\n amarokData.delegate = bridgeData.receiver;\n amarokData.payFeeWithSendingAsset = true;\n\n return (bridgeData, amarokData);\n }\n\n /// @notice Decodes calldata for startBridgeTokensViaAmarokERC20PackedPayFeeWithNative\n /// @param _data the calldata to decode\n function decode_startBridgeTokensViaAmarokERC20PackedPayFeeWithNative(\n bytes calldata _data\n )\n external\n pure\n returns (BridgeData memory, AmarokFacet.AmarokData memory)\n {\n require(\n _data.length >= 76,\n \"data passed in is not the correct length\"\n );\n\n BridgeData memory bridgeData;\n AmarokFacet.AmarokData memory amarokData;\n\n uint32 destChainDomainId = uint32(bytes4(_data[68:72]));\n\n bridgeData.transactionId = bytes32(bytes8(_data[4:12]));\n bridgeData.receiver = address(bytes20(_data[12:32]));\n bridgeData.destinationChainId = getChainIdForDomain(destChainDomainId);\n bridgeData.sendingAssetId = address(bytes20(_data[32:52]));\n bridgeData.minAmount = uint256(uint128(bytes16(_data[52:68])));\n\n amarokData.callData = \"\";\n amarokData.callTo = bridgeData.receiver;\n amarokData.destChainDomainId = destChainDomainId;\n amarokData.slippageTol = uint256(\n uint128(uint32(bytes4(_data[72:76])))\n );\n amarokData.delegate = bridgeData.receiver;\n amarokData.payFeeWithSendingAsset = false;\n\n return (bridgeData, amarokData);\n }\n\n function getChainIdForDomain(\n uint32 domainId\n ) public pure returns (uint32 chainId) {\n if (domainId == 6648936) return 1;\n // ETH\n else if (domainId == 1886350457) return 137;\n // POL\n else if (domainId == 6450786) return 56;\n // BSC\n else if (domainId == 1869640809) return 10;\n // OPT\n else if (domainId == 6778479) return 100;\n // GNO/DAI\n else if (domainId == 1634886255) return 42161;\n // ARB\n else if (domainId == 1818848877) return 59144; // LIN\n }\n}\n" + }, + "src/Interfaces/IConnextHandler.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IConnextHandler {\n /// @notice These are the call parameters that will remain constant between the\n /// two chains. They are supplied on `xcall` and should be asserted on `execute`\n /// @property to - The account that receives funds, in the event of a crosschain call,\n /// will receive funds if the call fails.\n /// @param to - The address you are sending funds (and potentially data) to\n /// @param callData - The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.\n /// @param originDomain - The originating domain (i.e. where `xcall` is called). Must match nomad domain schema\n /// @param destinationDomain - The final domain (i.e. where `execute` / `reconcile` are called). Must match nomad domain schema\n /// @param agent - An address who can execute txs on behalf of `to`, in addition to allowing relayers\n /// @param recovery - The address to send funds to if your `Executor.execute call` fails\n /// @param forceSlow - If true, will take slow liquidity path even if it is not a permissioned call\n /// @param receiveLocal - If true, will use the local nomad asset on the destination instead of adopted.\n /// @param callback - The address on the origin domain of the callback contract\n /// @param callbackFee - The relayer fee to execute the callback\n /// @param relayerFee - The amount of relayer fee the tx called xcall with\n /// @param slippageTol - Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)\n struct CallParams {\n address to;\n bytes callData;\n uint32 originDomain;\n uint32 destinationDomain;\n address agent;\n address recovery;\n bool forceSlow;\n bool receiveLocal;\n address callback;\n uint256 callbackFee;\n uint256 relayerFee;\n uint256 slippageTol;\n }\n\n /// @notice The arguments you supply to the `xcall` function called by user on origin domain\n /// @param params - The CallParams. These are consistent across sending and receiving chains\n /// @param transactingAsset - The asset the caller sent with the transfer. Can be the adopted, canonical,\n /// or the representational asset\n /// @param transactingAmount - The amount of transferring asset supplied by the user in the `xcall`\n /// @param originMinOut - Minimum amount received on swaps for adopted <> local on origin chain\n struct XCallArgs {\n CallParams params;\n address transactingAsset; // Could be adopted, local, or wrapped\n uint256 transactingAmount;\n uint256 originMinOut;\n }\n\n function xcall(\n uint32 destination,\n address recipient,\n address tokenAddress,\n address delegate,\n uint256 amount,\n uint256 slippage,\n bytes memory callData\n ) external payable returns (bytes32);\n\n function xcall(\n uint32 destination,\n address recipient,\n address tokenAddress,\n address delegate,\n uint256 amount,\n uint256 slippage,\n bytes memory callData,\n uint256 _relayerFee\n ) external returns (bytes32);\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "lib/solmate/src/utils/SafeTransferLib.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20} from \"../tokens/ERC20.sol\";\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n /*//////////////////////////////////////////////////////////////\n ETH OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferETH(address to, uint256 amount) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Transfer the ETH and store if it succeeded or not.\n success := call(gas(), to, amount, 0, 0, 0, 0)\n }\n\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferFrom(\n ERC20 token,\n address from,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), from) // Append the \"from\" argument.\n mstore(add(freeMemoryPointer, 36), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 68), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FROM_FAILED\");\n }\n\n function safeTransfer(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FAILED\");\n }\n\n function safeApprove(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"APPROVE_FAILED\");\n }\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/TransferrableOwnership.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IERC173 } from \"../Interfaces/IERC173.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\n\ncontract TransferrableOwnership is IERC173 {\n address public owner;\n address public pendingOwner;\n\n /// Errors ///\n error UnAuthorized();\n error NoNullOwner();\n error NewOwnerMustNotBeSelf();\n error NoPendingOwnershipTransfer();\n error NotPendingOwner();\n\n /// Events ///\n event OwnershipTransferRequested(\n address indexed _from,\n address indexed _to\n );\n\n constructor(address initialOwner) {\n owner = initialOwner;\n }\n\n modifier onlyOwner() {\n if (msg.sender != owner) revert UnAuthorized();\n _;\n }\n\n /// @notice Initiates transfer of ownership to a new address\n /// @param _newOwner the address to transfer ownership to\n function transferOwnership(address _newOwner) external onlyOwner {\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\n pendingOwner = _newOwner;\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\n }\n\n /// @notice Cancel transfer of ownership\n function cancelOwnershipTransfer() external onlyOwner {\n if (pendingOwner == LibAsset.NULL_ADDRESS)\n revert NoPendingOwnershipTransfer();\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\n function confirmOwnershipTransfer() external {\n address _pendingOwner = pendingOwner;\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n}\n" + }, + "src/Facets/AmarokFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IConnextHandler } from \"../Interfaces/IConnextHandler.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { InformationMismatch } from \"../Errors/GenericErrors.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title Amarok Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Connext Amarok\n/// @custom:version 2.0.0\ncontract AmarokFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n /// @notice The contract address of the connext handler on the source chain.\n IConnextHandler private immutable connextHandler;\n\n /// @param callData The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.\n /// @param callTo The address of the contract on dest chain that will receive bridged funds and execute data\n /// @param relayerFee The amount of relayer fee the tx called xcall with\n /// @param slippageTol Maximum acceptable slippage in BPS. For example, a value of 30 means 0.3% slippage\n /// @param delegate Destination delegate address\n /// @param destChainDomainId The Amarok-specific domainId of the destination chain\n /// @param payFeeWithSendingAsset Whether to pay the relayer fee with the sending asset or not\n struct AmarokData {\n bytes callData;\n address callTo;\n uint256 relayerFee;\n uint256 slippageTol;\n address delegate;\n uint32 destChainDomainId;\n bool payFeeWithSendingAsset;\n }\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _connextHandler The contract address of the connext handler on the source chain.\n constructor(IConnextHandler _connextHandler) {\n connextHandler = _connextHandler;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Amarok\n /// @param _bridgeData Data containing core information for bridging\n /// @param _amarokData Data specific to bridge\n function startBridgeTokensViaAmarok(\n BridgeData calldata _bridgeData,\n AmarokData calldata _amarokData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n noNativeAsset(_bridgeData)\n {\n validateDestinationCallFlag(_bridgeData, _amarokData);\n\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n\n _startBridge(_bridgeData, _amarokData);\n }\n\n /// @notice Performs a swap before bridging via Amarok\n /// @param _bridgeData The core information needed for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _amarokData Data specific to Amarok\n function swapAndStartBridgeTokensViaAmarok(\n BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n AmarokData calldata _amarokData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n noNativeAsset(_bridgeData)\n {\n validateDestinationCallFlag(_bridgeData, _amarokData);\n\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n _amarokData.relayerFee\n );\n\n _startBridge(_bridgeData, _amarokData);\n }\n\n /// Private Methods ///\n\n /// @dev Contains the business logic for the bridge via Amarok\n /// @param _bridgeData The core information needed for bridging\n /// @param _amarokData Data specific to Amarok\n function _startBridge(\n BridgeData memory _bridgeData,\n AmarokData calldata _amarokData\n ) private {\n // give max approval for token to Amarok bridge, if not already\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(connextHandler),\n _bridgeData.minAmount\n );\n\n // initiate bridge transaction\n if (_amarokData.payFeeWithSendingAsset) {\n connextHandler.xcall(\n _amarokData.destChainDomainId,\n _amarokData.callTo,\n _bridgeData.sendingAssetId,\n _amarokData.delegate,\n _bridgeData.minAmount - _amarokData.relayerFee,\n _amarokData.slippageTol,\n _amarokData.callData,\n _amarokData.relayerFee\n );\n } else {\n connextHandler.xcall{ value: _amarokData.relayerFee }(\n _amarokData.destChainDomainId,\n _amarokData.callTo,\n _bridgeData.sendingAssetId,\n _amarokData.delegate,\n _bridgeData.minAmount,\n _amarokData.slippageTol,\n _amarokData.callData\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n function validateDestinationCallFlag(\n ILiFi.BridgeData memory _bridgeData,\n AmarokData calldata _amarokData\n ) private pure {\n if (\n (_amarokData.callData.length > 0) != _bridgeData.hasDestinationCall\n ) {\n revert InformationMismatch();\n }\n }\n}\n" + }, + "lib/forge-std/src/console2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.22 <0.9.0;\n\n/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should\n/// use `int256` and `uint256`. This modified version fixes that. This version is recommended\n/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in\n/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.\n/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178\nlibrary console2 {\n address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);\n\n function _castLogPayloadViewToPure(\n function(bytes memory) internal view fnIn\n ) internal pure returns (function(bytes memory) internal pure fnOut) {\n assembly {\n fnOut := fnIn\n }\n }\n\n function _sendLogPayload(bytes memory payload) internal pure {\n _castLogPayloadViewToPure(_sendLogPayloadView)(payload);\n }\n\n function _sendLogPayloadView(bytes memory payload) private view {\n uint256 payloadLength = payload.length;\n address consoleAddress = CONSOLE_ADDRESS;\n /// @solidity memory-safe-assembly\n assembly {\n let payloadStart := add(payload, 32)\n let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)\n }\n }\n\n function log() internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log()\"));\n }\n\n function logInt(int256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function logUint(uint256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function logString(string memory p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function logBool(bool p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function logAddress(address p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function logBytes(bytes memory p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes)\", p0));\n }\n\n function logBytes1(bytes1 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes1)\", p0));\n }\n\n function logBytes2(bytes2 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes2)\", p0));\n }\n\n function logBytes3(bytes3 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes3)\", p0));\n }\n\n function logBytes4(bytes4 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes4)\", p0));\n }\n\n function logBytes5(bytes5 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes5)\", p0));\n }\n\n function logBytes6(bytes6 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes6)\", p0));\n }\n\n function logBytes7(bytes7 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes7)\", p0));\n }\n\n function logBytes8(bytes8 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes8)\", p0));\n }\n\n function logBytes9(bytes9 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes9)\", p0));\n }\n\n function logBytes10(bytes10 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes10)\", p0));\n }\n\n function logBytes11(bytes11 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes11)\", p0));\n }\n\n function logBytes12(bytes12 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes12)\", p0));\n }\n\n function logBytes13(bytes13 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes13)\", p0));\n }\n\n function logBytes14(bytes14 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes14)\", p0));\n }\n\n function logBytes15(bytes15 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes15)\", p0));\n }\n\n function logBytes16(bytes16 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes16)\", p0));\n }\n\n function logBytes17(bytes17 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes17)\", p0));\n }\n\n function logBytes18(bytes18 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes18)\", p0));\n }\n\n function logBytes19(bytes19 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes19)\", p0));\n }\n\n function logBytes20(bytes20 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes20)\", p0));\n }\n\n function logBytes21(bytes21 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes21)\", p0));\n }\n\n function logBytes22(bytes22 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes22)\", p0));\n }\n\n function logBytes23(bytes23 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes23)\", p0));\n }\n\n function logBytes24(bytes24 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes24)\", p0));\n }\n\n function logBytes25(bytes25 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes25)\", p0));\n }\n\n function logBytes26(bytes26 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes26)\", p0));\n }\n\n function logBytes27(bytes27 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes27)\", p0));\n }\n\n function logBytes28(bytes28 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes28)\", p0));\n }\n\n function logBytes29(bytes29 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes29)\", p0));\n }\n\n function logBytes30(bytes30 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes30)\", p0));\n }\n\n function logBytes31(bytes31 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes31)\", p0));\n }\n\n function logBytes32(bytes32 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bytes32)\", p0));\n }\n\n function log(uint256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256)\", p0));\n }\n\n function log(int256 p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(int256)\", p0));\n }\n\n function log(string memory p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string)\", p0));\n }\n\n function log(bool p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool)\", p0));\n }\n\n function log(address p0) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address)\", p0));\n }\n\n function log(uint256 p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256)\", p0, p1));\n }\n\n function log(uint256 p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string)\", p0, p1));\n }\n\n function log(uint256 p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool)\", p0, p1));\n }\n\n function log(uint256 p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address)\", p0, p1));\n }\n\n function log(string memory p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256)\", p0, p1));\n }\n\n function log(string memory p0, int256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,int256)\", p0, p1));\n }\n\n function log(string memory p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string)\", p0, p1));\n }\n\n function log(string memory p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool)\", p0, p1));\n }\n\n function log(string memory p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address)\", p0, p1));\n }\n\n function log(bool p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256)\", p0, p1));\n }\n\n function log(bool p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string)\", p0, p1));\n }\n\n function log(bool p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool)\", p0, p1));\n }\n\n function log(bool p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address)\", p0, p1));\n }\n\n function log(address p0, uint256 p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256)\", p0, p1));\n }\n\n function log(address p0, string memory p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string)\", p0, p1));\n }\n\n function log(address p0, bool p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool)\", p0, p1));\n }\n\n function log(address p0, address p1) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address)\", p0, p1));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool)\", p0, p1, p2));\n }\n\n function log(uint256 p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool)\", p0, p1, p2));\n }\n\n function log(string memory p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool)\", p0, p1, p2));\n }\n\n function log(bool p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool)\", p0, p1, p2));\n }\n\n function log(address p0, uint256 p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool)\", p0, p1, p2));\n }\n\n function log(address p0, string memory p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool)\", p0, p1, p2));\n }\n\n function log(address p0, bool p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, uint256 p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, string memory p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, bool p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool)\", p0, p1, p2));\n }\n\n function log(address p0, address p1, address p2) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address)\", p0, p1, p2));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(uint256 p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(uint256,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(string memory p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(string,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(bool p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(bool,address,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, uint256 p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,uint256,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, string memory p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,string,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, bool p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,bool,address,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, uint256 p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,uint256,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, string memory p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,string,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, bool p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,bool,address)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, uint256 p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,uint256)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, string memory p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,string)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, bool p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,bool)\", p0, p1, p2, p3));\n }\n\n function log(address p0, address p1, address p2, address p3) internal pure {\n _sendLogPayload(abi.encodeWithSignature(\"log(address,address,address,address)\", p0, p1, p2, p3));\n }\n\n}" + }, + "lib/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\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 ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Interfaces/IERC173.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\n/// @title ERC-173 Contract Ownership Standard\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\n/* is ERC165 */\ninterface IERC173 {\n /// @dev This emits when ownership of a contract changes.\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n /// @notice Get the address of the owner\n /// @return owner_ The address of the owner.\n function owner() external view returns (address owner_);\n\n /// @notice Set the address of the new owner of the contract\n /// @dev Set _newOwner to address(0) to renounce any ownership.\n /// @param _newOwner The address of the new owner of the contract\n function transferOwnership(address _newOwner) external;\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... -SymbiosisFacet +0xe12b2488c71432f9a116e9ac244d3ef4c2386d3a +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/SymbiosisFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { ISymbiosisMetaRouter } from \\\"../Interfaces/ISymbiosisMetaRouter.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\n\\n/// @title Symbiosis Facet\\n/// @author Symbiosis (https://symbiosis.finance)\\n/// @notice Provides functionality for bridging through Symbiosis Protocol\\n/// @custom:version 1.0.0\\ncontract SymbiosisFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// @notice The contract address of the Symbiosis router on the source chain\\n ISymbiosisMetaRouter private immutable symbiosisMetaRouter;\\n address private immutable symbiosisGateway;\\n\\n /// Types ///\\n struct SymbiosisData {\\n bytes firstSwapCalldata;\\n bytes secondSwapCalldata;\\n address intermediateToken;\\n address firstDexRouter;\\n address secondDexRouter;\\n address[] approvedTokens;\\n address callTo; // bridging entrypoint\\n bytes callData; // bridging calldata\\n }\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _symbiosisMetaRouter The contract address of the Symbiosis MetaRouter on the source chain.\\n /// @param _symbiosisGateway The contract address of the Symbiosis Gateway on the source chain.\\n constructor(\\n ISymbiosisMetaRouter _symbiosisMetaRouter,\\n address _symbiosisGateway\\n ) {\\n symbiosisMetaRouter = _symbiosisMetaRouter;\\n symbiosisGateway = _symbiosisGateway;\\n }\\n\\n /// @dev Contains the business logic for the bridge via Symbiosis\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _symbiosisData data specific to Symbiosis\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n SymbiosisData calldata _symbiosisData\\n ) internal {\\n bool isNative = LibAsset.isNativeAsset(_bridgeData.sendingAssetId);\\n uint256 nativeAssetAmount;\\n\\n if (isNative) {\\n nativeAssetAmount = _bridgeData.minAmount;\\n } else {\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n symbiosisGateway,\\n _bridgeData.minAmount\\n );\\n }\\n\\n symbiosisMetaRouter.metaRoute{ value: nativeAssetAmount }(\\n ISymbiosisMetaRouter.MetaRouteTransaction(\\n _symbiosisData.firstSwapCalldata,\\n _symbiosisData.secondSwapCalldata,\\n _symbiosisData.approvedTokens,\\n _symbiosisData.firstDexRouter,\\n _symbiosisData.secondDexRouter,\\n _bridgeData.minAmount,\\n isNative,\\n _symbiosisData.callTo,\\n _symbiosisData.callData\\n )\\n );\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Symbiosis\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _symbiosisData The data specific to Symbiosis\\n function startBridgeTokensViaSymbiosis(\\n ILiFi.BridgeData memory _bridgeData,\\n SymbiosisData calldata _symbiosisData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n validateBridgeData(_bridgeData)\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n\\n _startBridge(_bridgeData, _symbiosisData);\\n }\\n\\n /// @notice Performs a swap before bridging via Symbiosis\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _symbiosisData The data specific to Symbiosis\\n function swapAndStartBridgeTokensViaSymbiosis(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n SymbiosisData calldata _symbiosisData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n\\n _startBridge(_bridgeData, _symbiosisData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/ISymbiosisMetaRouter.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ISymbiosisMetaRouter {\\n /// @notice entry point data to Symbiosis contracts\\n /// @param firstSwapCalldata calldata for the dex swap to get corresponding asset (USDC) on init chain\\n /// @param secondSwapCalldata legacy calldata from v1, should be empty\\n /// @param approvedTokens set of token for firstSwapCalldata, and o bridgingCalldata\\n /// @param firstDexRouter entry point for firstSwapCalldata\\n /// @param secondDexRouter legacy entry point from v1, should be empty\\n /// @param amount of tokens\\n /// @param nativeIn native token in amount or not\\n /// @param relayRecipient entry point to bridge provided from API\\n /// @param otherSideCalldata bridging calldata\\n struct MetaRouteTransaction {\\n bytes firstSwapCalldata;\\n bytes secondSwapCalldata;\\n address[] approvedTokens;\\n address firstDexRouter;\\n address secondDexRouter;\\n uint256 amount;\\n bool nativeIn;\\n address relayRecipient;\\n bytes otherSideCalldata;\\n }\\n\\n /**\\n * @notice Method that starts the Meta Routing in Symbiosis\\n * @param _metarouteTransaction metaRoute offchain transaction data\\n */\\n function metaRoute(\\n MetaRouteTransaction calldata _metarouteTransaction\\n ) external payable;\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract ISymbiosisMetaRouter\",\"name\":\"_symbiosisMetaRouter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_symbiosisGateway\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"firstSwapCalldata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"secondSwapCalldata\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"intermediateToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"firstDexRouter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"secondDexRouter\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"approvedTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct SymbiosisFacet.SymbiosisData\",\"name\":\"_symbiosisData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaSymbiosis\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"firstSwapCalldata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"secondSwapCalldata\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"intermediateToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"firstDexRouter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"secondDexRouter\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"approvedTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"internalType\":\"struct SymbiosisFacet.SymbiosisData\",\"name\":\"_symbiosisData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaSymbiosis\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "SymbiosisFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "000000000000000000000000f621fb08bbe51af70e7e0f4ea63496894166ff7f000000000000000000000000fcef2fe72413b65d3f393d278a714cad87512bcd", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/SymbiosisFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { ISymbiosisMetaRouter } from \"../Interfaces/ISymbiosisMetaRouter.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\n\n/// @title Symbiosis Facet\n/// @author Symbiosis (https://symbiosis.finance)\n/// @notice Provides functionality for bridging through Symbiosis Protocol\n/// @custom:version 1.0.0\ncontract SymbiosisFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// @notice The contract address of the Symbiosis router on the source chain\n ISymbiosisMetaRouter private immutable symbiosisMetaRouter;\n address private immutable symbiosisGateway;\n\n /// Types ///\n struct SymbiosisData {\n bytes firstSwapCalldata;\n bytes secondSwapCalldata;\n address intermediateToken;\n address firstDexRouter;\n address secondDexRouter;\n address[] approvedTokens;\n address callTo; // bridging entrypoint\n bytes callData; // bridging calldata\n }\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _symbiosisMetaRouter The contract address of the Symbiosis MetaRouter on the source chain.\n /// @param _symbiosisGateway The contract address of the Symbiosis Gateway on the source chain.\n constructor(\n ISymbiosisMetaRouter _symbiosisMetaRouter,\n address _symbiosisGateway\n ) {\n symbiosisMetaRouter = _symbiosisMetaRouter;\n symbiosisGateway = _symbiosisGateway;\n }\n\n /// @dev Contains the business logic for the bridge via Symbiosis\n /// @param _bridgeData the core information needed for bridging\n /// @param _symbiosisData data specific to Symbiosis\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n SymbiosisData calldata _symbiosisData\n ) internal {\n bool isNative = LibAsset.isNativeAsset(_bridgeData.sendingAssetId);\n uint256 nativeAssetAmount;\n\n if (isNative) {\n nativeAssetAmount = _bridgeData.minAmount;\n } else {\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n symbiosisGateway,\n _bridgeData.minAmount\n );\n }\n\n symbiosisMetaRouter.metaRoute{ value: nativeAssetAmount }(\n ISymbiosisMetaRouter.MetaRouteTransaction(\n _symbiosisData.firstSwapCalldata,\n _symbiosisData.secondSwapCalldata,\n _symbiosisData.approvedTokens,\n _symbiosisData.firstDexRouter,\n _symbiosisData.secondDexRouter,\n _bridgeData.minAmount,\n isNative,\n _symbiosisData.callTo,\n _symbiosisData.callData\n )\n );\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Symbiosis\n /// @param _bridgeData The core information needed for bridging\n /// @param _symbiosisData The data specific to Symbiosis\n function startBridgeTokensViaSymbiosis(\n ILiFi.BridgeData memory _bridgeData,\n SymbiosisData calldata _symbiosisData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n validateBridgeData(_bridgeData)\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n\n _startBridge(_bridgeData, _symbiosisData);\n }\n\n /// @notice Performs a swap before bridging via Symbiosis\n /// @param _bridgeData The core information needed for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _symbiosisData The data specific to Symbiosis\n function swapAndStartBridgeTokensViaSymbiosis(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n SymbiosisData calldata _symbiosisData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n\n _startBridge(_bridgeData, _symbiosisData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/ISymbiosisMetaRouter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ISymbiosisMetaRouter {\n /// @notice entry point data to Symbiosis contracts\n /// @param firstSwapCalldata calldata for the dex swap to get corresponding asset (USDC) on init chain\n /// @param secondSwapCalldata legacy calldata from v1, should be empty\n /// @param approvedTokens set of token for firstSwapCalldata, and o bridgingCalldata\n /// @param firstDexRouter entry point for firstSwapCalldata\n /// @param secondDexRouter legacy entry point from v1, should be empty\n /// @param amount of tokens\n /// @param nativeIn native token in amount or not\n /// @param relayRecipient entry point to bridge provided from API\n /// @param otherSideCalldata bridging calldata\n struct MetaRouteTransaction {\n bytes firstSwapCalldata;\n bytes secondSwapCalldata;\n address[] approvedTokens;\n address firstDexRouter;\n address secondDexRouter;\n uint256 amount;\n bool nativeIn;\n address relayRecipient;\n bytes otherSideCalldata;\n }\n\n /**\n * @notice Method that starts the Meta Routing in Symbiosis\n * @param _metarouteTransaction metaRoute offchain transaction data\n */\n function metaRoute(\n MetaRouteTransaction calldata _metarouteTransaction\n ) external payable;\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... /SquidFacet +0x5c2c3f56e33f45389aa4e1da4d3a807a532a910c +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/SquidFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { ISquidRouter } from \\\"../Interfaces/ISquidRouter.sol\\\";\\nimport { ISquidMulticall } from \\\"../Interfaces/ISquidMulticall.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2 } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { LibBytes } from \\\"../Libraries/LibBytes.sol\\\";\\nimport { InformationMismatch } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ERC20 } from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\n\\n/// @title Squid Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Squid Router\\n/// @custom:version 1.0.0\\ncontract SquidFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Types ///\\n\\n enum RouteType {\\n BridgeCall,\\n CallBridge,\\n CallBridgeCall\\n }\\n\\n /// @dev Contains the data needed for bridging via Squid squidRouter\\n /// @param RouteType The type of route to use\\n /// @param destinationChain The chain to bridge tokens to\\n /// @param destinationAddress The receiver address in dst chain format\\n /// @param bridgedTokenSymbol The symbol of the to-be-bridged token\\n /// @param depositAssetId The asset to be deposited on src network (input for optional Squid-internal src swaps)\\n /// @param sourceCalls The calls to be made by Squid on the source chain before bridging the bridgeData.sendingAsssetId token\\n /// @param payload The payload for the calls to be made at dest chain\\n /// @param fee The fee to be payed in native token on src chain\\n /// @param enableExpress enable Squid Router's instant execution service\\n struct SquidData {\\n RouteType routeType;\\n string destinationChain;\\n string destinationAddress; // required to allow future bridging to non-EVM networks\\n string bridgedTokenSymbol;\\n address depositAssetId;\\n ISquidMulticall.Call[] sourceCalls;\\n bytes payload;\\n uint256 fee;\\n bool enableExpress;\\n }\\n\\n // introduced to tacke a stack-too-deep error\\n struct BridgeContext {\\n ILiFi.BridgeData bridgeData;\\n SquidData squidData;\\n uint256 msgValue;\\n }\\n\\n /// Errors ///\\n error InvalidRouteType();\\n\\n /// State ///\\n\\n ISquidRouter private immutable squidRouter;\\n\\n /// Constructor ///\\n\\n constructor(ISquidRouter _squidRouter) {\\n squidRouter = _squidRouter;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Squid Router\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _squidData Data specific to Squid Router\\n function startBridgeTokensViaSquid(\\n ILiFi.BridgeData memory _bridgeData,\\n SquidData calldata _squidData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _squidData.depositAssetId,\\n _bridgeData.minAmount\\n );\\n\\n _startBridge(_bridgeData, _squidData);\\n }\\n\\n /// @notice Swaps and bridges tokens via Squid Router\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _squidData Data specific to Squid Router\\n function swapAndStartBridgeTokensViaSquid(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n SquidData calldata _squidData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n // in case of native we need to keep the fee as reserve from the swap\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n _squidData.fee\\n );\\n\\n _startBridge(_bridgeData, _squidData);\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Squid Router\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _squidData Data specific to Squid Router\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n SquidData calldata _squidData\\n ) internal {\\n BridgeContext memory context = BridgeContext({\\n bridgeData: _bridgeData,\\n squidData: _squidData,\\n msgValue: _calculateMsgValue(_bridgeData, _squidData)\\n });\\n\\n // ensure max approval if non-native asset\\n if (!LibAsset.isNativeAsset(context.squidData.depositAssetId)) {\\n LibAsset.maxApproveERC20(\\n IERC20(context.squidData.depositAssetId),\\n address(squidRouter),\\n context.bridgeData.minAmount\\n );\\n }\\n\\n // make the call to Squid router based on RouteType\\n if (_squidData.routeType == RouteType.BridgeCall) {\\n _bridgeCall(context);\\n } else if (_squidData.routeType == RouteType.CallBridge) {\\n _callBridge(context);\\n } else if (_squidData.routeType == RouteType.CallBridgeCall) {\\n _callBridgeCall(context);\\n } else {\\n revert InvalidRouteType();\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n function _bridgeCall(BridgeContext memory _context) internal {\\n squidRouter.bridgeCall{ value: _context.msgValue }(\\n _context.squidData.bridgedTokenSymbol,\\n _context.bridgeData.minAmount,\\n _context.squidData.destinationChain,\\n _context.squidData.destinationAddress,\\n _context.squidData.payload,\\n _context.bridgeData.receiver,\\n _context.squidData.enableExpress\\n );\\n }\\n\\n function _callBridge(BridgeContext memory _context) private {\\n squidRouter.callBridge{ value: _context.msgValue }(\\n LibAsset.isNativeAsset(_context.squidData.depositAssetId)\\n ? 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\\n : _context.squidData.depositAssetId,\\n _context.bridgeData.minAmount,\\n _context.squidData.sourceCalls,\\n _context.squidData.bridgedTokenSymbol,\\n _context.squidData.destinationChain,\\n LibBytes.toHexString(uint160(_context.bridgeData.receiver), 20)\\n );\\n }\\n\\n function _callBridgeCall(BridgeContext memory _context) private {\\n squidRouter.callBridgeCall{ value: _context.msgValue }(\\n LibAsset.isNativeAsset(_context.squidData.depositAssetId)\\n ? 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\\n : _context.squidData.depositAssetId,\\n _context.bridgeData.minAmount,\\n _context.squidData.sourceCalls,\\n _context.squidData.bridgedTokenSymbol,\\n _context.squidData.destinationChain,\\n _context.squidData.destinationAddress,\\n _context.squidData.payload,\\n _context.bridgeData.receiver,\\n _context.squidData.enableExpress\\n );\\n }\\n\\n function _calculateMsgValue(\\n ILiFi.BridgeData memory _bridgeData,\\n SquidData calldata _squidData\\n ) private pure returns (uint256) {\\n uint256 msgValue = _squidData.fee;\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n msgValue += _bridgeData.minAmount;\\n }\\n return msgValue;\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/ISquidRouter.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ISquidMulticall } from \\\"./ISquidMulticall.sol\\\";\\n\\ninterface ISquidRouter {\\n function bridgeCall(\\n string calldata bridgedTokenSymbol,\\n uint256 amount,\\n string calldata destinationChain,\\n string calldata destinationAddress,\\n bytes calldata payload,\\n address gasRefundRecipient,\\n bool enableExpress\\n ) external payable;\\n\\n function callBridge(\\n address token,\\n uint256 amount,\\n ISquidMulticall.Call[] calldata calls,\\n string calldata bridgedTokenSymbol,\\n string calldata destinationChain,\\n string calldata destinationAddress\\n ) external payable;\\n\\n function callBridgeCall(\\n address token,\\n uint256 amount,\\n ISquidMulticall.Call[] calldata calls,\\n string calldata bridgedTokenSymbol,\\n string calldata destinationChain,\\n string calldata destinationAddress,\\n bytes calldata payload,\\n address gasRefundRecipient,\\n bool enableExpress\\n ) external payable;\\n}\\n\"\r\n },\r\n \"src/Interfaces/ISquidMulticall.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ISquidMulticall {\\n enum CallType {\\n Default,\\n FullTokenBalance,\\n FullNativeBalance,\\n CollectTokenBalance\\n }\\n\\n struct Call {\\n CallType callType;\\n address target;\\n uint256 value;\\n bytes callData;\\n bytes payload;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n string memory reason = LibUtil.getRevertMsg(res);\\n revert(reason);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\": {\r\n \"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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\": {\r\n \"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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Context.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract ISquidRouter\",\"name\":\"_squidRouter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRouteType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOutOfBounds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SliceOverflow\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"enum SquidFacet.RouteType\",\"name\":\"routeType\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"destinationChain\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destinationAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"bridgedTokenSymbol\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"depositAssetId\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"enum ISquidMulticall.CallType\",\"name\":\"callType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"internalType\":\"struct ISquidMulticall.Call[]\",\"name\":\"sourceCalls\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"enableExpress\",\"type\":\"bool\"}],\"internalType\":\"struct SquidFacet.SquidData\",\"name\":\"_squidData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaSquid\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"enum SquidFacet.RouteType\",\"name\":\"routeType\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"destinationChain\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"destinationAddress\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"bridgedTokenSymbol\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"depositAssetId\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"enum ISquidMulticall.CallType\",\"name\":\"callType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"internalType\":\"struct ISquidMulticall.Call[]\",\"name\":\"sourceCalls\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"enableExpress\",\"type\":\"bool\"}],\"internalType\":\"struct SquidFacet.SquidData\",\"name\":\"_squidData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaSquid\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "SquidFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "000000000000000000000000ce16f69375520ab01377ce7b88f5ba8c48f8d666", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/SquidFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { ISquidRouter } from \"../Interfaces/ISquidRouter.sol\";\nimport { ISquidMulticall } from \"../Interfaces/ISquidMulticall.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2 } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { LibBytes } from \"../Libraries/LibBytes.sol\";\nimport { InformationMismatch } from \"../Errors/GenericErrors.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n/// @title Squid Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Squid Router\n/// @custom:version 1.0.0\ncontract SquidFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Types ///\n\n enum RouteType {\n BridgeCall,\n CallBridge,\n CallBridgeCall\n }\n\n /// @dev Contains the data needed for bridging via Squid squidRouter\n /// @param RouteType The type of route to use\n /// @param destinationChain The chain to bridge tokens to\n /// @param destinationAddress The receiver address in dst chain format\n /// @param bridgedTokenSymbol The symbol of the to-be-bridged token\n /// @param depositAssetId The asset to be deposited on src network (input for optional Squid-internal src swaps)\n /// @param sourceCalls The calls to be made by Squid on the source chain before bridging the bridgeData.sendingAsssetId token\n /// @param payload The payload for the calls to be made at dest chain\n /// @param fee The fee to be payed in native token on src chain\n /// @param enableExpress enable Squid Router's instant execution service\n struct SquidData {\n RouteType routeType;\n string destinationChain;\n string destinationAddress; // required to allow future bridging to non-EVM networks\n string bridgedTokenSymbol;\n address depositAssetId;\n ISquidMulticall.Call[] sourceCalls;\n bytes payload;\n uint256 fee;\n bool enableExpress;\n }\n\n // introduced to tacke a stack-too-deep error\n struct BridgeContext {\n ILiFi.BridgeData bridgeData;\n SquidData squidData;\n uint256 msgValue;\n }\n\n /// Errors ///\n error InvalidRouteType();\n\n /// State ///\n\n ISquidRouter private immutable squidRouter;\n\n /// Constructor ///\n\n constructor(ISquidRouter _squidRouter) {\n squidRouter = _squidRouter;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Squid Router\n /// @param _bridgeData The core information needed for bridging\n /// @param _squidData Data specific to Squid Router\n function startBridgeTokensViaSquid(\n ILiFi.BridgeData memory _bridgeData,\n SquidData calldata _squidData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n LibAsset.depositAsset(\n _squidData.depositAssetId,\n _bridgeData.minAmount\n );\n\n _startBridge(_bridgeData, _squidData);\n }\n\n /// @notice Swaps and bridges tokens via Squid Router\n /// @param _bridgeData The core information needed for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _squidData Data specific to Squid Router\n function swapAndStartBridgeTokensViaSquid(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n SquidData calldata _squidData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n // in case of native we need to keep the fee as reserve from the swap\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n _squidData.fee\n );\n\n _startBridge(_bridgeData, _squidData);\n }\n\n /// Internal Methods ///\n\n /// @dev Contains the business logic for the bridge via Squid Router\n /// @param _bridgeData The core information needed for bridging\n /// @param _squidData Data specific to Squid Router\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n SquidData calldata _squidData\n ) internal {\n BridgeContext memory context = BridgeContext({\n bridgeData: _bridgeData,\n squidData: _squidData,\n msgValue: _calculateMsgValue(_bridgeData, _squidData)\n });\n\n // ensure max approval if non-native asset\n if (!LibAsset.isNativeAsset(context.squidData.depositAssetId)) {\n LibAsset.maxApproveERC20(\n IERC20(context.squidData.depositAssetId),\n address(squidRouter),\n context.bridgeData.minAmount\n );\n }\n\n // make the call to Squid router based on RouteType\n if (_squidData.routeType == RouteType.BridgeCall) {\n _bridgeCall(context);\n } else if (_squidData.routeType == RouteType.CallBridge) {\n _callBridge(context);\n } else if (_squidData.routeType == RouteType.CallBridgeCall) {\n _callBridgeCall(context);\n } else {\n revert InvalidRouteType();\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n function _bridgeCall(BridgeContext memory _context) internal {\n squidRouter.bridgeCall{ value: _context.msgValue }(\n _context.squidData.bridgedTokenSymbol,\n _context.bridgeData.minAmount,\n _context.squidData.destinationChain,\n _context.squidData.destinationAddress,\n _context.squidData.payload,\n _context.bridgeData.receiver,\n _context.squidData.enableExpress\n );\n }\n\n function _callBridge(BridgeContext memory _context) private {\n squidRouter.callBridge{ value: _context.msgValue }(\n LibAsset.isNativeAsset(_context.squidData.depositAssetId)\n ? 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\n : _context.squidData.depositAssetId,\n _context.bridgeData.minAmount,\n _context.squidData.sourceCalls,\n _context.squidData.bridgedTokenSymbol,\n _context.squidData.destinationChain,\n LibBytes.toHexString(uint160(_context.bridgeData.receiver), 20)\n );\n }\n\n function _callBridgeCall(BridgeContext memory _context) private {\n squidRouter.callBridgeCall{ value: _context.msgValue }(\n LibAsset.isNativeAsset(_context.squidData.depositAssetId)\n ? 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE\n : _context.squidData.depositAssetId,\n _context.bridgeData.minAmount,\n _context.squidData.sourceCalls,\n _context.squidData.bridgedTokenSymbol,\n _context.squidData.destinationChain,\n _context.squidData.destinationAddress,\n _context.squidData.payload,\n _context.bridgeData.receiver,\n _context.squidData.enableExpress\n );\n }\n\n function _calculateMsgValue(\n ILiFi.BridgeData memory _bridgeData,\n SquidData calldata _squidData\n ) private pure returns (uint256) {\n uint256 msgValue = _squidData.fee;\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n msgValue += _bridgeData.minAmount;\n }\n return msgValue;\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/ISquidRouter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ISquidMulticall } from \"./ISquidMulticall.sol\";\n\ninterface ISquidRouter {\n function bridgeCall(\n string calldata bridgedTokenSymbol,\n uint256 amount,\n string calldata destinationChain,\n string calldata destinationAddress,\n bytes calldata payload,\n address gasRefundRecipient,\n bool enableExpress\n ) external payable;\n\n function callBridge(\n address token,\n uint256 amount,\n ISquidMulticall.Call[] calldata calls,\n string calldata bridgedTokenSymbol,\n string calldata destinationChain,\n string calldata destinationAddress\n ) external payable;\n\n function callBridgeCall(\n address token,\n uint256 amount,\n ISquidMulticall.Call[] calldata calls,\n string calldata bridgedTokenSymbol,\n string calldata destinationChain,\n string calldata destinationAddress,\n bytes calldata payload,\n address gasRefundRecipient,\n bool enableExpress\n ) external payable;\n}\n" + }, + "src/Interfaces/ISquidMulticall.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ISquidMulticall {\n enum CallType {\n Default,\n FullTokenBalance,\n FullNativeBalance,\n CollectTokenBalance\n }\n\n struct Call {\n CallType callType;\n address target;\n uint256 value;\n bytes callData;\n bytes payload;\n }\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n string memory reason = LibUtil.getRevertMsg(res);\n revert(reason);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/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" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "lib/openzeppelin-contracts/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" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (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" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... |MayanFacet +0x4682d79dd4d0e7555415841b5151933af50594a8 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/MayanFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ERC20 } from \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2 } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { IMayan } from \\\"../Interfaces/IMayan.sol\\\";\\nimport { UnsupportedChainId } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Mayan Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Mayan Bridge\\n/// @custom:version 1.0.0\\ncontract MayanFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n bytes32 internal constant NAMESPACE = keccak256(\\\"com.lifi.facets.mayan\\\");\\n address internal constant NON_EVM_ADDRESS =\\n 0x11f111f111f111F111f111f111F111f111f111F1;\\n\\n IMayan public immutable mayan;\\n\\n /// @dev Mayan specific bridge data\\n /// @param nonEVMReceiver The address of the non-EVM receiver if applicable\\n /// @param mayanProtocol The address of the Mayan protocol final contract\\n /// @param protocolData The protocol data for the Mayan protocol\\n struct MayanData {\\n bytes32 nonEVMReceiver;\\n address mayanProtocol;\\n bytes protocolData;\\n }\\n\\n /// Errors ///\\n error InvalidReceiver(address expected, address actual);\\n error InvalidNonEVMReceiver(bytes32 expected, bytes32 actual);\\n\\n /// Events ///\\n\\n event BridgeToNonEVMChain(\\n bytes32 indexed transactionId,\\n uint256 indexed destinationChainId,\\n bytes32 receiver\\n );\\n\\n /// Constructor ///\\n\\n /// @notice Constructor for the contract.\\n constructor(IMayan _mayan) {\\n mayan = _mayan;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Mayan\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _mayanData Data specific to Mayan\\n function startBridgeTokensViaMayan(\\n ILiFi.BridgeData memory _bridgeData,\\n MayanData calldata _mayanData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n validateBridgeData(_bridgeData)\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // Normalize the amount to 8 decimals\\n _bridgeData.minAmount = _normalizeAmount(\\n _bridgeData.minAmount,\\n 18\\n );\\n }\\n\\n _startBridge(_bridgeData, _mayanData);\\n }\\n\\n /// @notice Performs a swap before bridging via Mayan\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _mayanData Data specific to Mayan\\n function swapAndStartBridgeTokensViaMayan(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n MayanData memory _mayanData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n\\n uint256 decimals;\\n bool isNative = LibAsset.isNativeAsset(_bridgeData.sendingAssetId);\\n decimals = isNative\\n ? 18\\n : ERC20(_bridgeData.sendingAssetId).decimals();\\n\\n // Normalize the amount to 8 decimals\\n _bridgeData.minAmount = _normalizeAmount(\\n _bridgeData.minAmount,\\n uint8(decimals)\\n );\\n\\n // Native values are not passed as calldata\\n if (!isNative) {\\n // Update the protocol data with the new input amount\\n _mayanData.protocolData = _replaceInputAmount(\\n _mayanData.protocolData,\\n _bridgeData.minAmount\\n );\\n }\\n\\n _startBridge(_bridgeData, _mayanData);\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Mayan\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _mayanData Data specific to Mayan\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n MayanData memory _mayanData\\n ) internal {\\n // Validate receiver address\\n if (_bridgeData.receiver == NON_EVM_ADDRESS) {\\n if (_mayanData.nonEVMReceiver == bytes32(0)) {\\n revert InvalidNonEVMReceiver(\\n _mayanData.nonEVMReceiver,\\n bytes32(0)\\n );\\n }\\n bytes32 receiver = _parseReceiver(_mayanData.protocolData);\\n if (_mayanData.nonEVMReceiver != receiver) {\\n revert InvalidNonEVMReceiver(\\n _mayanData.nonEVMReceiver,\\n receiver\\n );\\n }\\n } else {\\n address receiver = address(\\n uint160(uint256(_parseReceiver(_mayanData.protocolData)))\\n );\\n if (_bridgeData.receiver != receiver) {\\n revert InvalidReceiver(_bridgeData.receiver, receiver);\\n }\\n }\\n\\n IMayan.PermitParams memory emptyPermitParams;\\n\\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(mayan),\\n _bridgeData.minAmount\\n );\\n\\n mayan.forwardERC20(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount,\\n emptyPermitParams,\\n _mayanData.mayanProtocol,\\n _mayanData.protocolData\\n );\\n } else {\\n mayan.forwardEth{ value: _bridgeData.minAmount }(\\n _mayanData.mayanProtocol,\\n _mayanData.protocolData\\n );\\n }\\n\\n if (_bridgeData.receiver == NON_EVM_ADDRESS) {\\n emit BridgeToNonEVMChain(\\n _bridgeData.transactionId,\\n _bridgeData.destinationChainId,\\n _mayanData.nonEVMReceiver\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n // @dev Parses the receiver address from the protocol data\\n // @param protocolData The protocol data for the Mayan protocol\\n // @return receiver The receiver address\\n function _parseReceiver(\\n bytes memory protocolData\\n ) internal pure returns (bytes32 receiver) {\\n bytes4 selector;\\n assembly {\\n // Load the selector from the protocol data\\n selector := mload(add(protocolData, 0x20))\\n // Shift the selector to the right by 224 bits to match shape of literal in switch statement\\n let shiftedSelector := shr(224, selector)\\n switch shiftedSelector\\n // Note: [*bytes32*] = location of receiver address\\n case 0x94454a5d {\\n // 0x94454a5d bridgeWithFee(address,uint256,uint64,uint64,[*bytes32*],(uint32,bytes32,bytes32))\\n receiver := mload(add(protocolData, 0xa4)) // MayanCircle::bridgeWithFee()\\n }\\n case 0x32ad465f {\\n // 0x32ad465f bridgeWithLockedFee(address,uint256,uint64,uint256,(uint32,[*bytes32*],bytes32))\\n receiver := mload(add(protocolData, 0xc4)) // MayanCircle::bridgeWithLockedFee()\\n }\\n case 0xafd9b706 {\\n // 0xafd9b706 createOrder((address,uint256,uint64,[*bytes32*],uint16,bytes32,uint64,uint64,uint64,bytes32,uint8),(uint32,bytes32,bytes32))\\n receiver := mload(add(protocolData, 0x84)) // MayanCircle::createOrder()\\n }\\n case 0x6111ad25 {\\n // 0x6111ad25 swap((uint64,uint64,uint64),(bytes32,uint16,bytes32,[*bytes32*],uint16,bytes32,bytes32),bytes32,uint16,(uint256,uint64,uint64,bool,uint64,bytes),address,uint256)\\n receiver := mload(add(protocolData, 0xe4)) // MayanSwap::swap()\\n }\\n case 0x1eb1cff0 {\\n // 0x1eb1cff0 wrapAndSwapETH((uint64,uint64,uint64),(bytes32,uint16,bytes32,[*bytes32*],uint16,bytes32,bytes32),bytes32,uint16,(uint256,uint64,uint64,bool,uint64,bytes))\\n receiver := mload(add(protocolData, 0xe4)) // MayanSwap::wrapAndSwapETH()\\n }\\n case 0xb866e173 {\\n // 0xb866e173 createOrderWithEth((bytes32,bytes32,uint64,uint64,uint64,uint64,uint64,[*bytes32*],uint16,bytes32,uint8,uint8,bytes32))\\n receiver := mload(add(protocolData, 0x104)) // MayanSwift::createOrderWithEth()\\n }\\n case 0x8e8d142b {\\n // 0x8e8d142b createOrderWithToken(address,uint256,(bytes32,bytes32,uint64,uint64,uint64,uint64,uint64,[*bytes32*],uint16,bytes32,uint8,uint8,bytes32))\\n receiver := mload(add(protocolData, 0x144)) // MayanSwift::createOrderWithToken()\\n }\\n default {\\n receiver := 0x0\\n }\\n }\\n }\\n\\n // @dev Normalizes the amount to 8 decimals\\n // @param amount The amount to normalize\\n // @param decimals The number of decimals in the asset\\n function _normalizeAmount(\\n uint256 amount,\\n uint8 decimals\\n ) internal pure returns (uint256) {\\n if (decimals > 8) {\\n amount /= 10 ** (decimals - 8);\\n amount *= 10 ** (decimals - 8);\\n }\\n return amount;\\n }\\n\\n // @dev Replaces the input amount in the protocol data\\n // @param protocolData The protocol data for the Mayan protocol\\n // @param inputAmount The new input amount\\n // @return modifiedData The modified protocol data\\n function _replaceInputAmount(\\n bytes memory protocolData,\\n uint256 inputAmount\\n ) internal pure returns (bytes memory) {\\n require(protocolData.length >= 68, \\\"protocol data too short\\\");\\n bytes memory modifiedData = new bytes(protocolData.length);\\n bytes4 functionSelector = bytes4(protocolData[0]) |\\n (bytes4(protocolData[1]) >> 8) |\\n (bytes4(protocolData[2]) >> 16) |\\n (bytes4(protocolData[3]) >> 24);\\n\\n uint256 amountIndex;\\n // Only the wh swap method has the amount as last argument\\n bytes4 swapSelector = 0x6111ad25;\\n if (functionSelector == swapSelector) {\\n amountIndex = protocolData.length - 256;\\n } else {\\n amountIndex = 36;\\n }\\n\\n // Copy the function selector and params before amount in\\n for (uint i = 0; i < amountIndex; i++) {\\n modifiedData[i] = protocolData[i];\\n }\\n\\n // Encode the amount and place it into the modified call data\\n bytes memory encodedAmount = abi.encode(inputAmount);\\n for (uint i = 0; i < 32; i++) {\\n modifiedData[i + amountIndex] = encodedAmount[i];\\n }\\n\\n // Copy the rest of the original data after the input argument\\n for (uint i = amountIndex + 32; i < protocolData.length; i++) {\\n modifiedData[i] = protocolData[i];\\n }\\n\\n return modifiedData;\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n LibUtil.revertWith(res);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IMayan.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IMayan {\\n struct PermitParams {\\n uint256 value;\\n uint256 deadline;\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n function forwardEth(\\n address mayanProtocol,\\n bytes calldata protocolData\\n ) external payable;\\n\\n function forwardERC20(\\n address tokenIn,\\n uint256 amountIn,\\n PermitParams calldata permitParams,\\n address mayanProtocol,\\n bytes calldata protocolData\\n ) external payable;\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n\\n function revertWith(bytes memory data) internal pure {\\n assembly {\\n let dataSize := mload(data) // Load the size of the data\\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\\n revert(dataPtr, dataSize) // Revert with the given data\\n }\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol\": {\r\n \"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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Context.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (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\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\",\r\n \"solady/=lib/solady/src/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IMayan\",\"name\":\"_mayan\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"InvalidNonEVMReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"expected\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"actual\",\"type\":\"address\"}],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"receiver\",\"type\":\"bytes32\"}],\"name\":\"BridgeToNonEVMChain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"mayan\",\"outputs\":[{\"internalType\":\"contract IMayan\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"nonEVMReceiver\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"mayanProtocol\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"protocolData\",\"type\":\"bytes\"}],\"internalType\":\"struct MayanFacet.MayanData\",\"name\":\"_mayanData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaMayan\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"nonEVMReceiver\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"mayanProtocol\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"protocolData\",\"type\":\"bytes\"}],\"internalType\":\"struct MayanFacet.MayanData\",\"name\":\"_mayanData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaMayan\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "MayanFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000000654874eb7f59c6f5b39931fc45dc45337c967c3", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/MayanFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2 } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { IMayan } from \"../Interfaces/IMayan.sol\";\nimport { UnsupportedChainId } from \"../Errors/GenericErrors.sol\";\n\n/// @title Mayan Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Mayan Bridge\n/// @custom:version 1.0.0\ncontract MayanFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n bytes32 internal constant NAMESPACE = keccak256(\"com.lifi.facets.mayan\");\n address internal constant NON_EVM_ADDRESS =\n 0x11f111f111f111F111f111f111F111f111f111F1;\n\n IMayan public immutable mayan;\n\n /// @dev Mayan specific bridge data\n /// @param nonEVMReceiver The address of the non-EVM receiver if applicable\n /// @param mayanProtocol The address of the Mayan protocol final contract\n /// @param protocolData The protocol data for the Mayan protocol\n struct MayanData {\n bytes32 nonEVMReceiver;\n address mayanProtocol;\n bytes protocolData;\n }\n\n /// Errors ///\n error InvalidReceiver(address expected, address actual);\n error InvalidNonEVMReceiver(bytes32 expected, bytes32 actual);\n\n /// Events ///\n\n event BridgeToNonEVMChain(\n bytes32 indexed transactionId,\n uint256 indexed destinationChainId,\n bytes32 receiver\n );\n\n /// Constructor ///\n\n /// @notice Constructor for the contract.\n constructor(IMayan _mayan) {\n mayan = _mayan;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Mayan\n /// @param _bridgeData The core information needed for bridging\n /// @param _mayanData Data specific to Mayan\n function startBridgeTokensViaMayan(\n ILiFi.BridgeData memory _bridgeData,\n MayanData calldata _mayanData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n validateBridgeData(_bridgeData)\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // Normalize the amount to 8 decimals\n _bridgeData.minAmount = _normalizeAmount(\n _bridgeData.minAmount,\n 18\n );\n }\n\n _startBridge(_bridgeData, _mayanData);\n }\n\n /// @notice Performs a swap before bridging via Mayan\n /// @param _bridgeData The core information needed for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _mayanData Data specific to Mayan\n function swapAndStartBridgeTokensViaMayan(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n MayanData memory _mayanData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n\n uint256 decimals;\n bool isNative = LibAsset.isNativeAsset(_bridgeData.sendingAssetId);\n decimals = isNative\n ? 18\n : ERC20(_bridgeData.sendingAssetId).decimals();\n\n // Normalize the amount to 8 decimals\n _bridgeData.minAmount = _normalizeAmount(\n _bridgeData.minAmount,\n uint8(decimals)\n );\n\n // Native values are not passed as calldata\n if (!isNative) {\n // Update the protocol data with the new input amount\n _mayanData.protocolData = _replaceInputAmount(\n _mayanData.protocolData,\n _bridgeData.minAmount\n );\n }\n\n _startBridge(_bridgeData, _mayanData);\n }\n\n /// Internal Methods ///\n\n /// @dev Contains the business logic for the bridge via Mayan\n /// @param _bridgeData The core information needed for bridging\n /// @param _mayanData Data specific to Mayan\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n MayanData memory _mayanData\n ) internal {\n // Validate receiver address\n if (_bridgeData.receiver == NON_EVM_ADDRESS) {\n if (_mayanData.nonEVMReceiver == bytes32(0)) {\n revert InvalidNonEVMReceiver(\n _mayanData.nonEVMReceiver,\n bytes32(0)\n );\n }\n bytes32 receiver = _parseReceiver(_mayanData.protocolData);\n if (_mayanData.nonEVMReceiver != receiver) {\n revert InvalidNonEVMReceiver(\n _mayanData.nonEVMReceiver,\n receiver\n );\n }\n } else {\n address receiver = address(\n uint160(uint256(_parseReceiver(_mayanData.protocolData)))\n );\n if (_bridgeData.receiver != receiver) {\n revert InvalidReceiver(_bridgeData.receiver, receiver);\n }\n }\n\n IMayan.PermitParams memory emptyPermitParams;\n\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(mayan),\n _bridgeData.minAmount\n );\n\n mayan.forwardERC20(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount,\n emptyPermitParams,\n _mayanData.mayanProtocol,\n _mayanData.protocolData\n );\n } else {\n mayan.forwardEth{ value: _bridgeData.minAmount }(\n _mayanData.mayanProtocol,\n _mayanData.protocolData\n );\n }\n\n if (_bridgeData.receiver == NON_EVM_ADDRESS) {\n emit BridgeToNonEVMChain(\n _bridgeData.transactionId,\n _bridgeData.destinationChainId,\n _mayanData.nonEVMReceiver\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n // @dev Parses the receiver address from the protocol data\n // @param protocolData The protocol data for the Mayan protocol\n // @return receiver The receiver address\n function _parseReceiver(\n bytes memory protocolData\n ) internal pure returns (bytes32 receiver) {\n bytes4 selector;\n assembly {\n // Load the selector from the protocol data\n selector := mload(add(protocolData, 0x20))\n // Shift the selector to the right by 224 bits to match shape of literal in switch statement\n let shiftedSelector := shr(224, selector)\n switch shiftedSelector\n // Note: [*bytes32*] = location of receiver address\n case 0x94454a5d {\n // 0x94454a5d bridgeWithFee(address,uint256,uint64,uint64,[*bytes32*],(uint32,bytes32,bytes32))\n receiver := mload(add(protocolData, 0xa4)) // MayanCircle::bridgeWithFee()\n }\n case 0x32ad465f {\n // 0x32ad465f bridgeWithLockedFee(address,uint256,uint64,uint256,(uint32,[*bytes32*],bytes32))\n receiver := mload(add(protocolData, 0xc4)) // MayanCircle::bridgeWithLockedFee()\n }\n case 0xafd9b706 {\n // 0xafd9b706 createOrder((address,uint256,uint64,[*bytes32*],uint16,bytes32,uint64,uint64,uint64,bytes32,uint8),(uint32,bytes32,bytes32))\n receiver := mload(add(protocolData, 0x84)) // MayanCircle::createOrder()\n }\n case 0x6111ad25 {\n // 0x6111ad25 swap((uint64,uint64,uint64),(bytes32,uint16,bytes32,[*bytes32*],uint16,bytes32,bytes32),bytes32,uint16,(uint256,uint64,uint64,bool,uint64,bytes),address,uint256)\n receiver := mload(add(protocolData, 0xe4)) // MayanSwap::swap()\n }\n case 0x1eb1cff0 {\n // 0x1eb1cff0 wrapAndSwapETH((uint64,uint64,uint64),(bytes32,uint16,bytes32,[*bytes32*],uint16,bytes32,bytes32),bytes32,uint16,(uint256,uint64,uint64,bool,uint64,bytes))\n receiver := mload(add(protocolData, 0xe4)) // MayanSwap::wrapAndSwapETH()\n }\n case 0xb866e173 {\n // 0xb866e173 createOrderWithEth((bytes32,bytes32,uint64,uint64,uint64,uint64,uint64,[*bytes32*],uint16,bytes32,uint8,uint8,bytes32))\n receiver := mload(add(protocolData, 0x104)) // MayanSwift::createOrderWithEth()\n }\n case 0x8e8d142b {\n // 0x8e8d142b createOrderWithToken(address,uint256,(bytes32,bytes32,uint64,uint64,uint64,uint64,uint64,[*bytes32*],uint16,bytes32,uint8,uint8,bytes32))\n receiver := mload(add(protocolData, 0x144)) // MayanSwift::createOrderWithToken()\n }\n default {\n receiver := 0x0\n }\n }\n }\n\n // @dev Normalizes the amount to 8 decimals\n // @param amount The amount to normalize\n // @param decimals The number of decimals in the asset\n function _normalizeAmount(\n uint256 amount,\n uint8 decimals\n ) internal pure returns (uint256) {\n if (decimals > 8) {\n amount /= 10 ** (decimals - 8);\n amount *= 10 ** (decimals - 8);\n }\n return amount;\n }\n\n // @dev Replaces the input amount in the protocol data\n // @param protocolData The protocol data for the Mayan protocol\n // @param inputAmount The new input amount\n // @return modifiedData The modified protocol data\n function _replaceInputAmount(\n bytes memory protocolData,\n uint256 inputAmount\n ) internal pure returns (bytes memory) {\n require(protocolData.length >= 68, \"protocol data too short\");\n bytes memory modifiedData = new bytes(protocolData.length);\n bytes4 functionSelector = bytes4(protocolData[0]) |\n (bytes4(protocolData[1]) >> 8) |\n (bytes4(protocolData[2]) >> 16) |\n (bytes4(protocolData[3]) >> 24);\n\n uint256 amountIndex;\n // Only the wh swap method has the amount as last argument\n bytes4 swapSelector = 0x6111ad25;\n if (functionSelector == swapSelector) {\n amountIndex = protocolData.length - 256;\n } else {\n amountIndex = 36;\n }\n\n // Copy the function selector and params before amount in\n for (uint i = 0; i < amountIndex; i++) {\n modifiedData[i] = protocolData[i];\n }\n\n // Encode the amount and place it into the modified call data\n bytes memory encodedAmount = abi.encode(inputAmount);\n for (uint i = 0; i < 32; i++) {\n modifiedData[i + amountIndex] = encodedAmount[i];\n }\n\n // Copy the rest of the original data after the input argument\n for (uint i = amountIndex + 32; i < protocolData.length; i++) {\n modifiedData[i] = protocolData[i];\n }\n\n return modifiedData;\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n LibUtil.revertWith(res);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Interfaces/IMayan.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IMayan {\n struct PermitParams {\n uint256 value;\n uint256 deadline;\n uint8 v;\n bytes32 r;\n bytes32 s;\n }\n\n function forwardEth(\n address mayanProtocol,\n bytes calldata protocolData\n ) external payable;\n\n function forwardERC20(\n address tokenIn,\n uint256 amountIn,\n PermitParams calldata permitParams,\n address mayanProtocol,\n bytes calldata protocolData\n ) external payable;\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n\n function revertWith(bytes memory data) internal pure {\n assembly {\n let dataSize := mload(data) // Load the size of the data\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\n revert(dataPtr, dataSize) // Revert with the given data\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "lib/openzeppelin-contracts/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" + }, + "lib/openzeppelin-contracts/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (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" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/", + "solady/=lib/solady/src/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \StargateFacetV2 +0x6e378c84e657c57b2a8d183cff30ee5cc8989b61 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/StargateFacetV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IStargate, ITokenMessaging } from \\\"../Interfaces/IStargate.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { InformationMismatch } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { SwapperV2, LibSwap } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { SafeTransferLib } from \\\"solady/utils/SafeTransferLib.sol\\\";\\nimport { ERC20 } from \\\"solady/tokens/ERC20.sol\\\";\\n\\n/// @title StargateFacetV2\\n/// @author Li.Finance (https://li.finance)\\n/// @notice Provides functionality for bridging through Stargate (V2)\\n/// @custom:version 1.0.1\\ncontract StargateFacetV2 is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n using SafeTransferLib for address;\\n\\n /// STORAGE ///\\n ITokenMessaging public immutable tokenMessaging;\\n\\n /// @param assetId The Stargate-specific assetId for the token that should be bridged\\n /// @param sendParams Various parameters that describe what needs to be bridged, how to bridge it and what to do with it on dst\\n /// @param fee Information about the (native) LayerZero fee that needs to be sent with the tx\\n /// @param refundAddress the address that is used for potential refunds\\n struct StargateData {\\n uint16 assetId;\\n IStargate.SendParam sendParams;\\n IStargate.MessagingFee fee;\\n address payable refundAddress;\\n }\\n\\n /// ERRORS ///\\n error InvalidAssetId(uint16 invalidAssetId);\\n\\n /// CONSTRUCTOR ///\\n /// @param _tokenMessaging The address of the tokenMessaging contract (used to obtain pool addresses)\\n constructor(address _tokenMessaging) {\\n tokenMessaging = ITokenMessaging(_tokenMessaging);\\n }\\n\\n /// EXTERNAL METHODS ///\\n\\n /// @notice Bridges tokens via Stargate Bridge\\n /// @param _bridgeData Data used purely for tracking and analytics\\n /// @param _stargateData Data specific to Stargate Bridge\\n function startBridgeTokensViaStargate(\\n ILiFi.BridgeData calldata _bridgeData,\\n StargateData calldata _stargateData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n doesNotContainSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData, _stargateData);\\n }\\n\\n /// @notice Performs a swap before bridging via Stargate Bridge\\n /// @param _bridgeData Data used purely for tracking and analytics\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _stargateData Data specific to Stargate Bridge\\n function swapAndStartBridgeTokensViaStargate(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n StargateData calldata _stargateData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n _stargateData.fee.nativeFee\\n );\\n\\n _startBridge(_bridgeData, _stargateData);\\n }\\n\\n /// PRIVATE METHODS ///\\n\\n /// @dev Contains the business logic for the bridging via StargateV2\\n /// @param _bridgeData Data used purely for tracking and analytics\\n /// @param _stargateData Data specific to Stargate Bridge\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n StargateData memory _stargateData\\n ) private {\\n // validate destination call flag\\n if (\\n (_stargateData.sendParams.composeMsg.length > 0 !=\\n _bridgeData.hasDestinationCall) ||\\n (_bridgeData.hasDestinationCall &&\\n _stargateData.sendParams.oftCmd.length != 0)\\n ) revert InformationMismatch();\\n\\n // ensure that receiver addresses match in case of no destination call\\n if (\\n !_bridgeData.hasDestinationCall &&\\n (_bridgeData.receiver !=\\n address(uint160(uint256(_stargateData.sendParams.to))))\\n ) revert InformationMismatch();\\n\\n // get the router-/pool address through the TokenMessaging contract\\n address routerAddress = tokenMessaging.stargateImpls(\\n _stargateData.assetId\\n );\\n if (routerAddress == address(0))\\n revert InvalidAssetId(_stargateData.assetId);\\n\\n // check if NATIVE or ERC20\\n uint256 msgValue = _stargateData.fee.nativeFee;\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // NATIVE\\n // add minAmount to msgValue\\n msgValue += _bridgeData.minAmount;\\n } else {\\n // ERC20\\n // check current allowance to router\\n address sendingAssetId = _bridgeData.sendingAssetId;\\n uint256 currentAllowance = ERC20(sendingAssetId).allowance(\\n address(this),\\n routerAddress\\n );\\n // check if allowance is sufficient\\n if (currentAllowance < _bridgeData.minAmount) {\\n // check if allowance is 0\\n if (currentAllowance != 0) {\\n sendingAssetId.safeApprove(routerAddress, 0);\\n }\\n // set allowance to uintMax\\n sendingAssetId.safeApprove(routerAddress, type(uint256).max);\\n }\\n }\\n\\n // update amount in sendParams\\n _stargateData.sendParams.amountLD = _bridgeData.minAmount;\\n\\n // execute call to Stargate router\\n IStargate(routerAddress).sendToken{ value: msgValue }(\\n _stargateData.sendParams,\\n _stargateData.fee,\\n _stargateData.refundAddress\\n );\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IStargate.sol\": {\r\n \"content\": \"// Interface for Stargate V2\\n\\n// SPDX-License-Identifier: BUSL-1.1\\npragma solidity =0.8.17;\\n\\n/// @notice Stargate implementation type.\\nenum StargateType {\\n Pool,\\n OFT\\n}\\n\\n/// @notice Ticket data for bus ride.\\nstruct Ticket {\\n uint72 ticketId;\\n bytes passengerBytes;\\n}\\n\\n/// @title Interface for Stargate.\\n/// @notice Defines an API for sending tokens to destination chains.\\ninterface IStargate {\\n /**\\n * @dev Struct representing token parameters for the OFT send() operation.\\n */\\n struct SendParam {\\n uint32 dstEid; // Destination endpoint ID.\\n bytes32 to; // Recipient address.\\n uint256 amountLD; // Amount to send in local decimals.\\n uint256 minAmountLD; // Minimum amount to send in local decimals.\\n bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message.\\n bytes composeMsg; // The composed message for the send() operation.\\n bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations.\\n }\\n\\n /**\\n * @dev Struct representing OFT limit information.\\n * @dev These amounts can change dynamically and are up the the specific oft implementation.\\n */\\n struct OFTLimit {\\n uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient.\\n uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient.\\n }\\n\\n /**\\n * @dev Struct representing OFT receipt information.\\n */\\n struct OFTReceipt {\\n uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals.\\n // @dev In non-default implementations, the amountReceivedLD COULD differ from this value.\\n uint256 amountReceivedLD; // Amount of tokens to be received on the remote side.\\n }\\n\\n /**\\n * @dev Struct representing OFT fee details.\\n * @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI.\\n */\\n struct OFTFeeDetail {\\n int256 feeAmountLD; // Amount of the fee in local decimals.\\n string description; // Description of the fee.\\n }\\n\\n struct MessagingFee {\\n uint256 nativeFee;\\n uint256 lzTokenFee;\\n }\\n\\n struct MessagingReceipt {\\n bytes32 guid;\\n uint64 nonce;\\n MessagingFee fee;\\n }\\n\\n /// @dev This function is same as `send` in OFT interface but returns the ticket data if in the bus ride mode,\\n /// which allows the caller to ride and drive the bus in the same transaction.\\n function sendToken(\\n SendParam calldata _sendParam,\\n MessagingFee calldata _fee,\\n address _refundAddress\\n )\\n external\\n payable\\n returns (\\n MessagingReceipt memory msgReceipt,\\n OFTReceipt memory oftReceipt,\\n Ticket memory ticket\\n );\\n\\n /**\\n * @notice Provides a quote for OFT-related operations.\\n * @param _sendParam The parameters for the send operation.\\n * @return limit The OFT limit information.\\n * @return oftFeeDetails The details of OFT fees.\\n * @return receipt The OFT receipt information.\\n */\\n function quoteOFT(\\n SendParam calldata _sendParam\\n )\\n external\\n view\\n returns (\\n OFTLimit memory,\\n OFTFeeDetail[] memory oftFeeDetails,\\n OFTReceipt memory\\n );\\n\\n /**\\n * @notice Provides a quote for the send() operation.\\n * @param _sendParam The parameters for the send() operation.\\n * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.\\n * @return fee The calculated LayerZero messaging fee from the send() operation.\\n *\\n * @dev MessagingFee: LayerZero msg fee\\n * - nativeFee: The native fee.\\n * - lzTokenFee: The lzToken fee.\\n */\\n function quoteSend(\\n SendParam calldata _sendParam,\\n bool _payInLzToken\\n ) external view returns (MessagingFee memory);\\n}\\n\\ninterface ITokenMessaging {\\n function assetIds(address tokenAddress) external returns (uint16);\\n\\n function stargateImpls(uint16 assetId) external returns (address);\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror ExternalCallFailed();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"lib/solady/src/utils/SafeTransferLib.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)\\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\\n/// @author Permit2 operations from (https://github.com/Uniswap/permit2/blob/main/src/libraries/Permit2Lib.sol)\\n///\\n/// @dev Note:\\n/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.\\n/// - For ERC20s, this implementation won't check that a token has code,\\n/// responsibility is delegated to the caller.\\nlibrary SafeTransferLib {\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* CUSTOM ERRORS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev The ETH transfer has failed.\\n error ETHTransferFailed();\\n\\n /// @dev The ERC20 `transferFrom` has failed.\\n error TransferFromFailed();\\n\\n /// @dev The ERC20 `transfer` has failed.\\n error TransferFailed();\\n\\n /// @dev The ERC20 `approve` has failed.\\n error ApproveFailed();\\n\\n /// @dev The Permit2 operation has failed.\\n error Permit2Failed();\\n\\n /// @dev The Permit2 amount must be less than `2**160 - 1`.\\n error Permit2AmountOverflow();\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* CONSTANTS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.\\n uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;\\n\\n /// @dev Suggested gas stipend for contract receiving ETH to perform a few\\n /// storage reads and writes, but low enough to prevent griefing.\\n uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;\\n\\n /// @dev The unique EIP-712 domain domain separator for the DAI token contract.\\n bytes32 internal constant DAI_DOMAIN_SEPARATOR =\\n 0xdbb8cf42e1ecb028be3f3dbc922e1d878b963f411dc388ced501601c60f7c6f7;\\n\\n /// @dev The address for the WETH9 contract on Ethereum mainnet.\\n address internal constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\\n\\n /// @dev The canonical Permit2 address.\\n /// [Github](https://github.com/Uniswap/permit2)\\n /// [Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3)\\n address internal constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* ETH OPERATIONS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.\\n //\\n // The regular variants:\\n // - Forwards all remaining gas to the target.\\n // - Reverts if the target reverts.\\n // - Reverts if the current contract has insufficient balance.\\n //\\n // The force variants:\\n // - Forwards with an optional gas stipend\\n // (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).\\n // - If the target reverts, or if the gas stipend is exhausted,\\n // creates a temporary contract to force send the ETH via `SELFDESTRUCT`.\\n // Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.\\n // - Reverts if the current contract has insufficient balance.\\n //\\n // The try variants:\\n // - Forwards with a mandatory gas stipend.\\n // - Instead of reverting, returns whether the transfer succeeded.\\n\\n /// @dev Sends `amount` (in wei) ETH to `to`.\\n function safeTransferETH(address to, uint256 amount) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {\\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n }\\n }\\n\\n /// @dev Sends all the ETH in the current contract to `to`.\\n function safeTransferAllETH(address to) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Transfer all the ETH and check if it succeeded or not.\\n if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n }\\n }\\n\\n /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\\n function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n if lt(selfbalance(), amount) {\\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) {\\n mstore(0x00, to) // Store the address in scratch space.\\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\\n if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\\n }\\n }\\n }\\n\\n /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.\\n function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\\n mstore(0x00, to) // Store the address in scratch space.\\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\\n if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\\n }\\n }\\n }\\n\\n /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.\\n function forceSafeTransferETH(address to, uint256 amount) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n if lt(selfbalance(), amount) {\\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) {\\n mstore(0x00, to) // Store the address in scratch space.\\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\\n if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\\n }\\n }\\n }\\n\\n /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.\\n function forceSafeTransferAllETH(address to) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // forgefmt: disable-next-item\\n if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\\n mstore(0x00, to) // Store the address in scratch space.\\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\\n if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\\n }\\n }\\n }\\n\\n /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\\n function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)\\n internal\\n returns (bool success)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)\\n }\\n }\\n\\n /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.\\n function trySafeTransferAllETH(address to, uint256 gasStipend)\\n internal\\n returns (bool success)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)\\n }\\n }\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* ERC20 OPERATIONS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\\n /// Reverts upon failure.\\n ///\\n /// The `from` account must have at least `amount` approved for\\n /// the current contract to manage.\\n function safeTransferFrom(address token, address from, address to, uint256 amount) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40) // Cache the free memory pointer.\\n mstore(0x60, amount) // Store the `amount` argument.\\n mstore(0x40, to) // Store the `to` argument.\\n mstore(0x2c, shl(96, from)) // Store the `from` argument.\\n mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.\\n // Perform the transfer, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x60, 0) // Restore the zero slot to zero.\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\\n ///\\n /// The `from` account must have at least `amount` approved for the current contract to manage.\\n function trySafeTransferFrom(address token, address from, address to, uint256 amount)\\n internal\\n returns (bool success)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40) // Cache the free memory pointer.\\n mstore(0x60, amount) // Store the `amount` argument.\\n mstore(0x40, to) // Store the `to` argument.\\n mstore(0x2c, shl(96, from)) // Store the `from` argument.\\n mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.\\n success :=\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\\n )\\n mstore(0x60, 0) // Restore the zero slot to zero.\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /// @dev Sends all of ERC20 `token` from `from` to `to`.\\n /// Reverts upon failure.\\n ///\\n /// The `from` account must have their entire balance approved for the current contract to manage.\\n function safeTransferAllFrom(address token, address from, address to)\\n internal\\n returns (uint256 amount)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40) // Cache the free memory pointer.\\n mstore(0x40, to) // Store the `to` argument.\\n mstore(0x2c, shl(96, from)) // Store the `from` argument.\\n mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.\\n // Read the balance, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\\n staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.\\n amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.\\n // Perform the transfer, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x60, 0) // Restore the zero slot to zero.\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.\\n /// Reverts upon failure.\\n function safeTransfer(address token, address to, uint256 amount) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x14, to) // Store the `to` argument.\\n mstore(0x34, amount) // Store the `amount` argument.\\n mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.\\n // Perform the transfer, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\\n }\\n }\\n\\n /// @dev Sends all of ERC20 `token` from the current contract to `to`.\\n /// Reverts upon failure.\\n function safeTransferAll(address token, address to) internal returns (uint256 amount) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.\\n mstore(0x20, address()) // Store the address of the current contract.\\n // Read the balance, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\\n staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x14, to) // Store the `to` argument.\\n amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.\\n mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.\\n // Perform the transfer, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\\n }\\n }\\n\\n /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.\\n /// Reverts upon failure.\\n function safeApprove(address token, address to, uint256 amount) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x14, to) // Store the `to` argument.\\n mstore(0x34, amount) // Store the `amount` argument.\\n mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\\n // Perform the approval, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\\n }\\n }\\n\\n /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.\\n /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,\\n /// then retries the approval again (some tokens, e.g. USDT, requires this).\\n /// Reverts upon failure.\\n function safeApproveWithRetry(address token, address to, uint256 amount) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x14, to) // Store the `to` argument.\\n mstore(0x34, amount) // Store the `amount` argument.\\n mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\\n // Perform the approval, retrying upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x34, 0) // Store 0 for the `amount`.\\n mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\\n pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval.\\n mstore(0x34, amount) // Store back the original `amount`.\\n // Retry the approval, reverting upon failure.\\n if iszero(\\n and(\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.\\n revert(0x1c, 0x04)\\n }\\n }\\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\\n }\\n }\\n\\n /// @dev Returns the amount of ERC20 `token` owned by `account`.\\n /// Returns zero if the `token` does not exist.\\n function balanceOf(address token, address account) internal view returns (uint256 amount) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x14, account) // Store the `account` argument.\\n mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.\\n amount :=\\n mul( // The arguments of `mul` are evaluated from right to left.\\n mload(0x20),\\n and( // The arguments of `and` are evaluated from right to left.\\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\\n staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)\\n )\\n )\\n }\\n }\\n\\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\\n /// If the initial attempt fails, try to use Permit2 to transfer the token.\\n /// Reverts upon failure.\\n ///\\n /// The `from` account must have at least `amount` approved for the current contract to manage.\\n function safeTransferFrom2(address token, address from, address to, uint256 amount) internal {\\n if (!trySafeTransferFrom(token, from, to, amount)) {\\n permit2TransferFrom(token, from, to, amount);\\n }\\n }\\n\\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to` via Permit2.\\n /// Reverts upon failure.\\n function permit2TransferFrom(address token, address from, address to, uint256 amount)\\n internal\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40)\\n mstore(add(m, 0x74), shr(96, shl(96, token)))\\n mstore(add(m, 0x54), amount)\\n mstore(add(m, 0x34), to)\\n mstore(add(m, 0x20), shl(96, from))\\n // `transferFrom(address,address,uint160,address)`.\\n mstore(m, 0x36c78516000000000000000000000000)\\n let p := PERMIT2\\n let exists := eq(chainid(), 1)\\n if iszero(exists) { exists := iszero(iszero(extcodesize(p))) }\\n if iszero(and(call(gas(), p, 0, add(m, 0x10), 0x84, codesize(), 0x00), exists)) {\\n mstore(0x00, 0x7939f4248757f0fd) // `TransferFromFailed()` or `Permit2AmountOverflow()`.\\n revert(add(0x18, shl(2, iszero(iszero(shr(160, amount))))), 0x04)\\n }\\n }\\n }\\n\\n /// @dev Permit a user to spend a given amount of\\n /// another user's tokens via native EIP-2612 permit if possible, falling\\n /// back to Permit2 if native permit fails or is not implemented on the token.\\n function permit2(\\n address token,\\n address owner,\\n address spender,\\n uint256 amount,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n bool success;\\n /// @solidity memory-safe-assembly\\n assembly {\\n for {} shl(96, xor(token, WETH9)) {} {\\n mstore(0x00, 0x3644e515) // `DOMAIN_SEPARATOR()`.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n lt(iszero(mload(0x00)), eq(returndatasize(), 0x20)), // Returns 1 non-zero word.\\n // Gas stipend to limit gas burn for tokens that don't refund gas when\\n // an non-existing function is called. 5K should be enough for a SLOAD.\\n staticcall(5000, token, 0x1c, 0x04, 0x00, 0x20)\\n )\\n ) { break }\\n // After here, we can be sure that token is a contract.\\n let m := mload(0x40)\\n mstore(add(m, 0x34), spender)\\n mstore(add(m, 0x20), shl(96, owner))\\n mstore(add(m, 0x74), deadline)\\n if eq(mload(0x00), DAI_DOMAIN_SEPARATOR) {\\n mstore(0x14, owner)\\n mstore(0x00, 0x7ecebe00000000000000000000000000) // `nonces(address)`.\\n mstore(add(m, 0x94), staticcall(gas(), token, 0x10, 0x24, add(m, 0x54), 0x20))\\n mstore(m, 0x8fcbaf0c000000000000000000000000) // `IDAIPermit.permit`.\\n // `nonces` is already at `add(m, 0x54)`.\\n // `1` is already stored at `add(m, 0x94)`.\\n mstore(add(m, 0xb4), and(0xff, v))\\n mstore(add(m, 0xd4), r)\\n mstore(add(m, 0xf4), s)\\n success := call(gas(), token, 0, add(m, 0x10), 0x104, codesize(), 0x00)\\n break\\n }\\n mstore(m, 0xd505accf000000000000000000000000) // `IERC20Permit.permit`.\\n mstore(add(m, 0x54), amount)\\n mstore(add(m, 0x94), and(0xff, v))\\n mstore(add(m, 0xb4), r)\\n mstore(add(m, 0xd4), s)\\n success := call(gas(), token, 0, add(m, 0x10), 0xe4, codesize(), 0x00)\\n break\\n }\\n }\\n if (!success) simplePermit2(token, owner, spender, amount, deadline, v, r, s);\\n }\\n\\n /// @dev Simple permit on the Permit2 contract.\\n function simplePermit2(\\n address token,\\n address owner,\\n address spender,\\n uint256 amount,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40)\\n mstore(m, 0x927da105) // `allowance(address,address,address)`.\\n {\\n let addressMask := shr(96, not(0))\\n mstore(add(m, 0x20), and(addressMask, owner))\\n mstore(add(m, 0x40), and(addressMask, token))\\n mstore(add(m, 0x60), and(addressMask, spender))\\n mstore(add(m, 0xc0), and(addressMask, spender))\\n }\\n let p := mul(PERMIT2, iszero(shr(160, amount)))\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n gt(returndatasize(), 0x5f), // Returns 3 words: `amount`, `expiration`, `nonce`.\\n staticcall(gas(), p, add(m, 0x1c), 0x64, add(m, 0x60), 0x60)\\n )\\n ) {\\n mstore(0x00, 0x6b836e6b8757f0fd) // `Permit2Failed()` or `Permit2AmountOverflow()`.\\n revert(add(0x18, shl(2, iszero(p))), 0x04)\\n }\\n mstore(m, 0x2b67b570) // `Permit2.permit` (PermitSingle variant).\\n // `owner` is already `add(m, 0x20)`.\\n // `token` is already at `add(m, 0x40)`.\\n mstore(add(m, 0x60), amount)\\n mstore(add(m, 0x80), 0xffffffffffff) // `expiration = type(uint48).max`.\\n // `nonce` is already at `add(m, 0xa0)`.\\n // `spender` is already at `add(m, 0xc0)`.\\n mstore(add(m, 0xe0), deadline)\\n mstore(add(m, 0x100), 0x100) // `signature` offset.\\n mstore(add(m, 0x120), 0x41) // `signature` length.\\n mstore(add(m, 0x140), r)\\n mstore(add(m, 0x160), s)\\n mstore(add(m, 0x180), shl(248, v))\\n if iszero(call(gas(), p, 0, add(m, 0x1c), 0x184, codesize(), 0x00)) {\\n mstore(0x00, 0x6b836e6b) // `Permit2Failed()`.\\n revert(0x1c, 0x04)\\n }\\n }\\n }\\n}\\n\"\r\n },\r\n \"lib/solady/src/tokens/ERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n/// @notice Simple ERC20 + EIP-2612 implementation.\\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC20.sol)\\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)\\n///\\n/// @dev Note:\\n/// - The ERC20 standard allows minting and transferring to and from the zero address,\\n/// minting and transferring zero tokens, as well as self-approvals.\\n/// For performance, this implementation WILL NOT revert for such actions.\\n/// Please add any checks with overrides if desired.\\n/// - The `permit` function uses the ecrecover precompile (0x1).\\n///\\n/// If you are overriding:\\n/// - NEVER violate the ERC20 invariant:\\n/// the total sum of all balances must be equal to `totalSupply()`.\\n/// - Check that the overridden function is actually used in the function you want to\\n/// change the behavior of. Much of the code has been manually inlined for performance.\\nabstract contract ERC20 {\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* CUSTOM ERRORS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev The total supply has overflowed.\\n error TotalSupplyOverflow();\\n\\n /// @dev The allowance has overflowed.\\n error AllowanceOverflow();\\n\\n /// @dev The allowance has underflowed.\\n error AllowanceUnderflow();\\n\\n /// @dev Insufficient balance.\\n error InsufficientBalance();\\n\\n /// @dev Insufficient allowance.\\n error InsufficientAllowance();\\n\\n /// @dev The permit is invalid.\\n error InvalidPermit();\\n\\n /// @dev The permit has expired.\\n error PermitExpired();\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* EVENTS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Emitted when `amount` tokens is transferred from `from` to `to`.\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /// @dev Emitted when `amount` tokens is approved by `owner` to be used by `spender`.\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /// @dev `keccak256(bytes(\\\"Transfer(address,address,uint256)\\\"))`.\\n uint256 private constant _TRANSFER_EVENT_SIGNATURE =\\n 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;\\n\\n /// @dev `keccak256(bytes(\\\"Approval(address,address,uint256)\\\"))`.\\n uint256 private constant _APPROVAL_EVENT_SIGNATURE =\\n 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* STORAGE */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev The storage slot for the total supply.\\n uint256 private constant _TOTAL_SUPPLY_SLOT = 0x05345cdf77eb68f44c;\\n\\n /// @dev The balance slot of `owner` is given by:\\n /// ```\\n /// mstore(0x0c, _BALANCE_SLOT_SEED)\\n /// mstore(0x00, owner)\\n /// let balanceSlot := keccak256(0x0c, 0x20)\\n /// ```\\n uint256 private constant _BALANCE_SLOT_SEED = 0x87a211a2;\\n\\n /// @dev The allowance slot of (`owner`, `spender`) is given by:\\n /// ```\\n /// mstore(0x20, spender)\\n /// mstore(0x0c, _ALLOWANCE_SLOT_SEED)\\n /// mstore(0x00, owner)\\n /// let allowanceSlot := keccak256(0x0c, 0x34)\\n /// ```\\n uint256 private constant _ALLOWANCE_SLOT_SEED = 0x7f5e9f20;\\n\\n /// @dev The nonce slot of `owner` is given by:\\n /// ```\\n /// mstore(0x0c, _NONCES_SLOT_SEED)\\n /// mstore(0x00, owner)\\n /// let nonceSlot := keccak256(0x0c, 0x20)\\n /// ```\\n uint256 private constant _NONCES_SLOT_SEED = 0x38377508;\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* CONSTANTS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev `(_NONCES_SLOT_SEED << 16) | 0x1901`.\\n uint256 private constant _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX = 0x383775081901;\\n\\n /// @dev `keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\")`.\\n bytes32 private constant _DOMAIN_TYPEHASH =\\n 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;\\n\\n /// @dev `keccak256(\\\"1\\\")`.\\n bytes32 private constant _VERSION_HASH =\\n 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6;\\n\\n /// @dev `keccak256(\\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\")`.\\n bytes32 private constant _PERMIT_TYPEHASH =\\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* ERC20 METADATA */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Returns the name of the token.\\n function name() public view virtual returns (string memory);\\n\\n /// @dev Returns the symbol of the token.\\n function symbol() public view virtual returns (string memory);\\n\\n /// @dev Returns the decimals places of the token.\\n function decimals() public view virtual returns (uint8) {\\n return 18;\\n }\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* ERC20 */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Returns the amount of tokens in existence.\\n function totalSupply() public view virtual returns (uint256 result) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := sload(_TOTAL_SUPPLY_SLOT)\\n }\\n }\\n\\n /// @dev Returns the amount of tokens owned by `owner`.\\n function balanceOf(address owner) public view virtual returns (uint256 result) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x0c, _BALANCE_SLOT_SEED)\\n mstore(0x00, owner)\\n result := sload(keccak256(0x0c, 0x20))\\n }\\n }\\n\\n /// @dev Returns the amount of tokens that `spender` can spend on behalf of `owner`.\\n function allowance(address owner, address spender)\\n public\\n view\\n virtual\\n returns (uint256 result)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x20, spender)\\n mstore(0x0c, _ALLOWANCE_SLOT_SEED)\\n mstore(0x00, owner)\\n result := sload(keccak256(0x0c, 0x34))\\n }\\n }\\n\\n /// @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n ///\\n /// Emits a {Approval} event.\\n function approve(address spender, uint256 amount) public virtual returns (bool) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Compute the allowance slot and store the amount.\\n mstore(0x20, spender)\\n mstore(0x0c, _ALLOWANCE_SLOT_SEED)\\n mstore(0x00, caller())\\n sstore(keccak256(0x0c, 0x34), amount)\\n // Emit the {Approval} event.\\n mstore(0x00, amount)\\n log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, caller(), shr(96, mload(0x2c)))\\n }\\n return true;\\n }\\n\\n /// @dev Transfer `amount` tokens from the caller to `to`.\\n ///\\n /// Requirements:\\n /// - `from` must at least have `amount`.\\n ///\\n /// Emits a {Transfer} event.\\n function transfer(address to, uint256 amount) public virtual returns (bool) {\\n _beforeTokenTransfer(msg.sender, to, amount);\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Compute the balance slot and load its value.\\n mstore(0x0c, _BALANCE_SLOT_SEED)\\n mstore(0x00, caller())\\n let fromBalanceSlot := keccak256(0x0c, 0x20)\\n let fromBalance := sload(fromBalanceSlot)\\n // Revert if insufficient balance.\\n if gt(amount, fromBalance) {\\n mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.\\n revert(0x1c, 0x04)\\n }\\n // Subtract and store the updated balance.\\n sstore(fromBalanceSlot, sub(fromBalance, amount))\\n // Compute the balance slot of `to`.\\n mstore(0x00, to)\\n let toBalanceSlot := keccak256(0x0c, 0x20)\\n // Add and store the updated balance of `to`.\\n // Will not overflow because the sum of all user balances\\n // cannot exceed the maximum uint256 value.\\n sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))\\n // Emit the {Transfer} event.\\n mstore(0x20, amount)\\n log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, caller(), shr(96, mload(0x0c)))\\n }\\n _afterTokenTransfer(msg.sender, to, amount);\\n return true;\\n }\\n\\n /// @dev Transfers `amount` tokens from `from` to `to`.\\n ///\\n /// Note: Does not update the allowance if it is the maximum uint256 value.\\n ///\\n /// Requirements:\\n /// - `from` must at least have `amount`.\\n /// - The caller must have at least `amount` of allowance to transfer the tokens of `from`.\\n ///\\n /// Emits a {Transfer} event.\\n function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {\\n _beforeTokenTransfer(from, to, amount);\\n /// @solidity memory-safe-assembly\\n assembly {\\n let from_ := shl(96, from)\\n // Compute the allowance slot and load its value.\\n mstore(0x20, caller())\\n mstore(0x0c, or(from_, _ALLOWANCE_SLOT_SEED))\\n let allowanceSlot := keccak256(0x0c, 0x34)\\n let allowance_ := sload(allowanceSlot)\\n // If the allowance is not the maximum uint256 value.\\n if add(allowance_, 1) {\\n // Revert if the amount to be transferred exceeds the allowance.\\n if gt(amount, allowance_) {\\n mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.\\n revert(0x1c, 0x04)\\n }\\n // Subtract and store the updated allowance.\\n sstore(allowanceSlot, sub(allowance_, amount))\\n }\\n // Compute the balance slot and load its value.\\n mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))\\n let fromBalanceSlot := keccak256(0x0c, 0x20)\\n let fromBalance := sload(fromBalanceSlot)\\n // Revert if insufficient balance.\\n if gt(amount, fromBalance) {\\n mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.\\n revert(0x1c, 0x04)\\n }\\n // Subtract and store the updated balance.\\n sstore(fromBalanceSlot, sub(fromBalance, amount))\\n // Compute the balance slot of `to`.\\n mstore(0x00, to)\\n let toBalanceSlot := keccak256(0x0c, 0x20)\\n // Add and store the updated balance of `to`.\\n // Will not overflow because the sum of all user balances\\n // cannot exceed the maximum uint256 value.\\n sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))\\n // Emit the {Transfer} event.\\n mstore(0x20, amount)\\n log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))\\n }\\n _afterTokenTransfer(from, to, amount);\\n return true;\\n }\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* EIP-2612 */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev For more performance, override to return the constant value\\n /// of `keccak256(bytes(name()))` if `name()` will never change.\\n function _constantNameHash() internal view virtual returns (bytes32 result) {}\\n\\n /// @dev Returns the current nonce for `owner`.\\n /// This value is used to compute the signature for EIP-2612 permit.\\n function nonces(address owner) public view virtual returns (uint256 result) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Compute the nonce slot and load its value.\\n mstore(0x0c, _NONCES_SLOT_SEED)\\n mstore(0x00, owner)\\n result := sload(keccak256(0x0c, 0x20))\\n }\\n }\\n\\n /// @dev Sets `value` as the allowance of `spender` over the tokens of `owner`,\\n /// authorized by a signed approval by `owner`.\\n ///\\n /// Emits a {Approval} event.\\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 ) public virtual {\\n bytes32 nameHash = _constantNameHash();\\n // We simply calculate it on-the-fly to allow for cases where the `name` may change.\\n if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Revert if the block timestamp is greater than `deadline`.\\n if gt(timestamp(), deadline) {\\n mstore(0x00, 0x1a15a3cc) // `PermitExpired()`.\\n revert(0x1c, 0x04)\\n }\\n let m := mload(0x40) // Grab the free memory pointer.\\n // Clean the upper 96 bits.\\n owner := shr(96, shl(96, owner))\\n spender := shr(96, shl(96, spender))\\n // Compute the nonce slot and load its value.\\n mstore(0x0e, _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX)\\n mstore(0x00, owner)\\n let nonceSlot := keccak256(0x0c, 0x20)\\n let nonceValue := sload(nonceSlot)\\n // Prepare the domain separator.\\n mstore(m, _DOMAIN_TYPEHASH)\\n mstore(add(m, 0x20), nameHash)\\n mstore(add(m, 0x40), _VERSION_HASH)\\n mstore(add(m, 0x60), chainid())\\n mstore(add(m, 0x80), address())\\n mstore(0x2e, keccak256(m, 0xa0))\\n // Prepare the struct hash.\\n mstore(m, _PERMIT_TYPEHASH)\\n mstore(add(m, 0x20), owner)\\n mstore(add(m, 0x40), spender)\\n mstore(add(m, 0x60), value)\\n mstore(add(m, 0x80), nonceValue)\\n mstore(add(m, 0xa0), deadline)\\n mstore(0x4e, keccak256(m, 0xc0))\\n // Prepare the ecrecover calldata.\\n mstore(0x00, keccak256(0x2c, 0x42))\\n mstore(0x20, and(0xff, v))\\n mstore(0x40, r)\\n mstore(0x60, s)\\n let t := staticcall(gas(), 1, 0, 0x80, 0x20, 0x20)\\n // If the ecrecover fails, the returndatasize will be 0x00,\\n // `owner` will be checked if it equals the hash at 0x00,\\n // which evaluates to false (i.e. 0), and we will revert.\\n // If the ecrecover succeeds, the returndatasize will be 0x20,\\n // `owner` will be compared against the returned address at 0x20.\\n if iszero(eq(mload(returndatasize()), owner)) {\\n mstore(0x00, 0xddafbaef) // `InvalidPermit()`.\\n revert(0x1c, 0x04)\\n }\\n // Increment and store the updated nonce.\\n sstore(nonceSlot, add(nonceValue, t)) // `t` is 1 if ecrecover succeeds.\\n // Compute the allowance slot and store the value.\\n // The `owner` is already at slot 0x20.\\n mstore(0x40, or(shl(160, _ALLOWANCE_SLOT_SEED), spender))\\n sstore(keccak256(0x2c, 0x34), value)\\n // Emit the {Approval} event.\\n log3(add(m, 0x60), 0x20, _APPROVAL_EVENT_SIGNATURE, owner, spender)\\n mstore(0x40, m) // Restore the free memory pointer.\\n mstore(0x60, 0) // Restore the zero pointer.\\n }\\n }\\n\\n /// @dev Returns the EIP-712 domain separator for the EIP-2612 permit.\\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) {\\n bytes32 nameHash = _constantNameHash();\\n // We simply calculate it on-the-fly to allow for cases where the `name` may change.\\n if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40) // Grab the free memory pointer.\\n mstore(m, _DOMAIN_TYPEHASH)\\n mstore(add(m, 0x20), nameHash)\\n mstore(add(m, 0x40), _VERSION_HASH)\\n mstore(add(m, 0x60), chainid())\\n mstore(add(m, 0x80), address())\\n result := keccak256(m, 0xa0)\\n }\\n }\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* INTERNAL MINT FUNCTIONS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Mints `amount` tokens to `to`, increasing the total supply.\\n ///\\n /// Emits a {Transfer} event.\\n function _mint(address to, uint256 amount) internal virtual {\\n _beforeTokenTransfer(address(0), to, amount);\\n /// @solidity memory-safe-assembly\\n assembly {\\n let totalSupplyBefore := sload(_TOTAL_SUPPLY_SLOT)\\n let totalSupplyAfter := add(totalSupplyBefore, amount)\\n // Revert if the total supply overflows.\\n if lt(totalSupplyAfter, totalSupplyBefore) {\\n mstore(0x00, 0xe5cfe957) // `TotalSupplyOverflow()`.\\n revert(0x1c, 0x04)\\n }\\n // Store the updated total supply.\\n sstore(_TOTAL_SUPPLY_SLOT, totalSupplyAfter)\\n // Compute the balance slot and load its value.\\n mstore(0x0c, _BALANCE_SLOT_SEED)\\n mstore(0x00, to)\\n let toBalanceSlot := keccak256(0x0c, 0x20)\\n // Add and store the updated balance.\\n sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))\\n // Emit the {Transfer} event.\\n mstore(0x20, amount)\\n log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, 0, shr(96, mload(0x0c)))\\n }\\n _afterTokenTransfer(address(0), to, amount);\\n }\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* INTERNAL BURN FUNCTIONS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Burns `amount` tokens from `from`, reducing the total supply.\\n ///\\n /// Emits a {Transfer} event.\\n function _burn(address from, uint256 amount) internal virtual {\\n _beforeTokenTransfer(from, address(0), amount);\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Compute the balance slot and load its value.\\n mstore(0x0c, _BALANCE_SLOT_SEED)\\n mstore(0x00, from)\\n let fromBalanceSlot := keccak256(0x0c, 0x20)\\n let fromBalance := sload(fromBalanceSlot)\\n // Revert if insufficient balance.\\n if gt(amount, fromBalance) {\\n mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.\\n revert(0x1c, 0x04)\\n }\\n // Subtract and store the updated balance.\\n sstore(fromBalanceSlot, sub(fromBalance, amount))\\n // Subtract and store the updated total supply.\\n sstore(_TOTAL_SUPPLY_SLOT, sub(sload(_TOTAL_SUPPLY_SLOT), amount))\\n // Emit the {Transfer} event.\\n mstore(0x00, amount)\\n log3(0x00, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, shl(96, from)), 0)\\n }\\n _afterTokenTransfer(from, address(0), amount);\\n }\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* INTERNAL TRANSFER FUNCTIONS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Moves `amount` of tokens from `from` to `to`.\\n function _transfer(address from, address to, uint256 amount) internal virtual {\\n _beforeTokenTransfer(from, to, amount);\\n /// @solidity memory-safe-assembly\\n assembly {\\n let from_ := shl(96, from)\\n // Compute the balance slot and load its value.\\n mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))\\n let fromBalanceSlot := keccak256(0x0c, 0x20)\\n let fromBalance := sload(fromBalanceSlot)\\n // Revert if insufficient balance.\\n if gt(amount, fromBalance) {\\n mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.\\n revert(0x1c, 0x04)\\n }\\n // Subtract and store the updated balance.\\n sstore(fromBalanceSlot, sub(fromBalance, amount))\\n // Compute the balance slot of `to`.\\n mstore(0x00, to)\\n let toBalanceSlot := keccak256(0x0c, 0x20)\\n // Add and store the updated balance of `to`.\\n // Will not overflow because the sum of all user balances\\n // cannot exceed the maximum uint256 value.\\n sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))\\n // Emit the {Transfer} event.\\n mstore(0x20, amount)\\n log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))\\n }\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* INTERNAL ALLOWANCE FUNCTIONS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Updates the allowance of `owner` for `spender` based on spent `amount`.\\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Compute the allowance slot and load its value.\\n mstore(0x20, spender)\\n mstore(0x0c, _ALLOWANCE_SLOT_SEED)\\n mstore(0x00, owner)\\n let allowanceSlot := keccak256(0x0c, 0x34)\\n let allowance_ := sload(allowanceSlot)\\n // If the allowance is not the maximum uint256 value.\\n if add(allowance_, 1) {\\n // Revert if the amount to be transferred exceeds the allowance.\\n if gt(amount, allowance_) {\\n mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.\\n revert(0x1c, 0x04)\\n }\\n // Subtract and store the updated allowance.\\n sstore(allowanceSlot, sub(allowance_, amount))\\n }\\n }\\n }\\n\\n /// @dev Sets `amount` as the allowance of `spender` over the tokens of `owner`.\\n ///\\n /// Emits a {Approval} event.\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let owner_ := shl(96, owner)\\n // Compute the allowance slot and store the amount.\\n mstore(0x20, spender)\\n mstore(0x0c, or(owner_, _ALLOWANCE_SLOT_SEED))\\n sstore(keccak256(0x0c, 0x34), amount)\\n // Emit the {Approval} event.\\n mstore(0x00, amount)\\n log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, shr(96, owner_), shr(96, mload(0x2c)))\\n }\\n }\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* HOOKS TO OVERRIDE */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Hook that is called before any transfer of tokens.\\n /// This includes minting and burning.\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n\\n /// @dev Hook that is called after any transfer of tokens.\\n /// This includes minting and burning.\\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n LibUtil.revertWith(res);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n\\n function revertWith(bytes memory data) internal pure {\\n assembly {\\n let dataSize := mload(data) // Load the size of the data\\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\\n revert(dataPtr, dataSize) // Revert with the given data\\n }\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"solady/=lib/solady/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_tokenMessaging\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"invalidAssetId\",\"type\":\"uint16\"}],\"name\":\"InvalidAssetId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint16\",\"name\":\"assetId\",\"type\":\"uint16\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct IStargate.SendParam\",\"name\":\"sendParams\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct IStargate.MessagingFee\",\"name\":\"fee\",\"type\":\"tuple\"},{\"internalType\":\"address payable\",\"name\":\"refundAddress\",\"type\":\"address\"}],\"internalType\":\"struct StargateFacetV2.StargateData\",\"name\":\"_stargateData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaStargate\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint16\",\"name\":\"assetId\",\"type\":\"uint16\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"dstEid\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"to\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"amountLD\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minAmountLD\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraOptions\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"composeMsg\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"oftCmd\",\"type\":\"bytes\"}],\"internalType\":\"struct IStargate.SendParam\",\"name\":\"sendParams\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"nativeFee\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lzTokenFee\",\"type\":\"uint256\"}],\"internalType\":\"struct IStargate.MessagingFee\",\"name\":\"fee\",\"type\":\"tuple\"},{\"internalType\":\"address payable\",\"name\":\"refundAddress\",\"type\":\"address\"}],\"internalType\":\"struct StargateFacetV2.StargateData\",\"name\":\"_stargateData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaStargate\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"tokenMessaging\",\"outputs\":[{\"internalType\":\"contract ITokenMessaging\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + ContractName: "StargateFacetV2", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000006d6620efa72948c5f68a3c8646d58c00d3f4a980", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/StargateFacetV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IStargate, ITokenMessaging } from \"../Interfaces/IStargate.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { InformationMismatch } from \"../Errors/GenericErrors.sol\";\nimport { SwapperV2, LibSwap } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { SafeTransferLib } from \"solady/utils/SafeTransferLib.sol\";\nimport { ERC20 } from \"solady/tokens/ERC20.sol\";\n\n/// @title StargateFacetV2\n/// @author Li.Finance (https://li.finance)\n/// @notice Provides functionality for bridging through Stargate (V2)\n/// @custom:version 1.0.1\ncontract StargateFacetV2 is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n using SafeTransferLib for address;\n\n /// STORAGE ///\n ITokenMessaging public immutable tokenMessaging;\n\n /// @param assetId The Stargate-specific assetId for the token that should be bridged\n /// @param sendParams Various parameters that describe what needs to be bridged, how to bridge it and what to do with it on dst\n /// @param fee Information about the (native) LayerZero fee that needs to be sent with the tx\n /// @param refundAddress the address that is used for potential refunds\n struct StargateData {\n uint16 assetId;\n IStargate.SendParam sendParams;\n IStargate.MessagingFee fee;\n address payable refundAddress;\n }\n\n /// ERRORS ///\n error InvalidAssetId(uint16 invalidAssetId);\n\n /// CONSTRUCTOR ///\n /// @param _tokenMessaging The address of the tokenMessaging contract (used to obtain pool addresses)\n constructor(address _tokenMessaging) {\n tokenMessaging = ITokenMessaging(_tokenMessaging);\n }\n\n /// EXTERNAL METHODS ///\n\n /// @notice Bridges tokens via Stargate Bridge\n /// @param _bridgeData Data used purely for tracking and analytics\n /// @param _stargateData Data specific to Stargate Bridge\n function startBridgeTokensViaStargate(\n ILiFi.BridgeData calldata _bridgeData,\n StargateData calldata _stargateData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n doesNotContainSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData, _stargateData);\n }\n\n /// @notice Performs a swap before bridging via Stargate Bridge\n /// @param _bridgeData Data used purely for tracking and analytics\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _stargateData Data specific to Stargate Bridge\n function swapAndStartBridgeTokensViaStargate(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n StargateData calldata _stargateData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n _stargateData.fee.nativeFee\n );\n\n _startBridge(_bridgeData, _stargateData);\n }\n\n /// PRIVATE METHODS ///\n\n /// @dev Contains the business logic for the bridging via StargateV2\n /// @param _bridgeData Data used purely for tracking and analytics\n /// @param _stargateData Data specific to Stargate Bridge\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n StargateData memory _stargateData\n ) private {\n // validate destination call flag\n if (\n (_stargateData.sendParams.composeMsg.length > 0 !=\n _bridgeData.hasDestinationCall) ||\n (_bridgeData.hasDestinationCall &&\n _stargateData.sendParams.oftCmd.length != 0)\n ) revert InformationMismatch();\n\n // ensure that receiver addresses match in case of no destination call\n if (\n !_bridgeData.hasDestinationCall &&\n (_bridgeData.receiver !=\n address(uint160(uint256(_stargateData.sendParams.to))))\n ) revert InformationMismatch();\n\n // get the router-/pool address through the TokenMessaging contract\n address routerAddress = tokenMessaging.stargateImpls(\n _stargateData.assetId\n );\n if (routerAddress == address(0))\n revert InvalidAssetId(_stargateData.assetId);\n\n // check if NATIVE or ERC20\n uint256 msgValue = _stargateData.fee.nativeFee;\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // NATIVE\n // add minAmount to msgValue\n msgValue += _bridgeData.minAmount;\n } else {\n // ERC20\n // check current allowance to router\n address sendingAssetId = _bridgeData.sendingAssetId;\n uint256 currentAllowance = ERC20(sendingAssetId).allowance(\n address(this),\n routerAddress\n );\n // check if allowance is sufficient\n if (currentAllowance < _bridgeData.minAmount) {\n // check if allowance is 0\n if (currentAllowance != 0) {\n sendingAssetId.safeApprove(routerAddress, 0);\n }\n // set allowance to uintMax\n sendingAssetId.safeApprove(routerAddress, type(uint256).max);\n }\n }\n\n // update amount in sendParams\n _stargateData.sendParams.amountLD = _bridgeData.minAmount;\n\n // execute call to Stargate router\n IStargate(routerAddress).sendToken{ value: msgValue }(\n _stargateData.sendParams,\n _stargateData.fee,\n _stargateData.refundAddress\n );\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IStargate.sol": { + "content": "// Interface for Stargate V2\n\n// SPDX-License-Identifier: BUSL-1.1\npragma solidity =0.8.17;\n\n/// @notice Stargate implementation type.\nenum StargateType {\n Pool,\n OFT\n}\n\n/// @notice Ticket data for bus ride.\nstruct Ticket {\n uint72 ticketId;\n bytes passengerBytes;\n}\n\n/// @title Interface for Stargate.\n/// @notice Defines an API for sending tokens to destination chains.\ninterface IStargate {\n /**\n * @dev Struct representing token parameters for the OFT send() operation.\n */\n struct SendParam {\n uint32 dstEid; // Destination endpoint ID.\n bytes32 to; // Recipient address.\n uint256 amountLD; // Amount to send in local decimals.\n uint256 minAmountLD; // Minimum amount to send in local decimals.\n bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message.\n bytes composeMsg; // The composed message for the send() operation.\n bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations.\n }\n\n /**\n * @dev Struct representing OFT limit information.\n * @dev These amounts can change dynamically and are up the the specific oft implementation.\n */\n struct OFTLimit {\n uint256 minAmountLD; // Minimum amount in local decimals that can be sent to the recipient.\n uint256 maxAmountLD; // Maximum amount in local decimals that can be sent to the recipient.\n }\n\n /**\n * @dev Struct representing OFT receipt information.\n */\n struct OFTReceipt {\n uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals.\n // @dev In non-default implementations, the amountReceivedLD COULD differ from this value.\n uint256 amountReceivedLD; // Amount of tokens to be received on the remote side.\n }\n\n /**\n * @dev Struct representing OFT fee details.\n * @dev Future proof mechanism to provide a standardized way to communicate fees to things like a UI.\n */\n struct OFTFeeDetail {\n int256 feeAmountLD; // Amount of the fee in local decimals.\n string description; // Description of the fee.\n }\n\n struct MessagingFee {\n uint256 nativeFee;\n uint256 lzTokenFee;\n }\n\n struct MessagingReceipt {\n bytes32 guid;\n uint64 nonce;\n MessagingFee fee;\n }\n\n /// @dev This function is same as `send` in OFT interface but returns the ticket data if in the bus ride mode,\n /// which allows the caller to ride and drive the bus in the same transaction.\n function sendToken(\n SendParam calldata _sendParam,\n MessagingFee calldata _fee,\n address _refundAddress\n )\n external\n payable\n returns (\n MessagingReceipt memory msgReceipt,\n OFTReceipt memory oftReceipt,\n Ticket memory ticket\n );\n\n /**\n * @notice Provides a quote for OFT-related operations.\n * @param _sendParam The parameters for the send operation.\n * @return limit The OFT limit information.\n * @return oftFeeDetails The details of OFT fees.\n * @return receipt The OFT receipt information.\n */\n function quoteOFT(\n SendParam calldata _sendParam\n )\n external\n view\n returns (\n OFTLimit memory,\n OFTFeeDetail[] memory oftFeeDetails,\n OFTReceipt memory\n );\n\n /**\n * @notice Provides a quote for the send() operation.\n * @param _sendParam The parameters for the send() operation.\n * @param _payInLzToken Flag indicating whether the caller is paying in the LZ token.\n * @return fee The calculated LayerZero messaging fee from the send() operation.\n *\n * @dev MessagingFee: LayerZero msg fee\n * - nativeFee: The native fee.\n * - lzTokenFee: The lzToken fee.\n */\n function quoteSend(\n SendParam calldata _sendParam,\n bool _payInLzToken\n ) external view returns (MessagingFee memory);\n}\n\ninterface ITokenMessaging {\n function assetIds(address tokenAddress) external returns (uint16);\n\n function stargateImpls(uint16 assetId) external returns (address);\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror ExternalCallFailed();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "lib/solady/src/utils/SafeTransferLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @author Permit2 operations from (https://github.com/Uniswap/permit2/blob/main/src/libraries/Permit2Lib.sol)\n///\n/// @dev Note:\n/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.\n/// - For ERC20s, this implementation won't check that a token has code,\n/// responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CUSTOM ERRORS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev The ETH transfer has failed.\n error ETHTransferFailed();\n\n /// @dev The ERC20 `transferFrom` has failed.\n error TransferFromFailed();\n\n /// @dev The ERC20 `transfer` has failed.\n error TransferFailed();\n\n /// @dev The ERC20 `approve` has failed.\n error ApproveFailed();\n\n /// @dev The Permit2 operation has failed.\n error Permit2Failed();\n\n /// @dev The Permit2 amount must be less than `2**160 - 1`.\n error Permit2AmountOverflow();\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CONSTANTS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.\n uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;\n\n /// @dev Suggested gas stipend for contract receiving ETH to perform a few\n /// storage reads and writes, but low enough to prevent griefing.\n uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;\n\n /// @dev The unique EIP-712 domain domain separator for the DAI token contract.\n bytes32 internal constant DAI_DOMAIN_SEPARATOR =\n 0xdbb8cf42e1ecb028be3f3dbc922e1d878b963f411dc388ced501601c60f7c6f7;\n\n /// @dev The address for the WETH9 contract on Ethereum mainnet.\n address internal constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n\n /// @dev The canonical Permit2 address.\n /// [Github](https://github.com/Uniswap/permit2)\n /// [Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3)\n address internal constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* ETH OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.\n //\n // The regular variants:\n // - Forwards all remaining gas to the target.\n // - Reverts if the target reverts.\n // - Reverts if the current contract has insufficient balance.\n //\n // The force variants:\n // - Forwards with an optional gas stipend\n // (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).\n // - If the target reverts, or if the gas stipend is exhausted,\n // creates a temporary contract to force send the ETH via `SELFDESTRUCT`.\n // Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.\n // - Reverts if the current contract has insufficient balance.\n //\n // The try variants:\n // - Forwards with a mandatory gas stipend.\n // - Instead of reverting, returns whether the transfer succeeded.\n\n /// @dev Sends `amount` (in wei) ETH to `to`.\n function safeTransferETH(address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Sends all the ETH in the current contract to `to`.\n function safeTransferAllETH(address to) internal {\n /// @solidity memory-safe-assembly\n assembly {\n // Transfer all the ETH and check if it succeeded or not.\n if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\n function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {\n /// @solidity memory-safe-assembly\n assembly {\n if lt(selfbalance(), amount) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, to) // Store the address in scratch space.\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\n }\n }\n }\n\n /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.\n function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {\n /// @solidity memory-safe-assembly\n assembly {\n if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, to) // Store the address in scratch space.\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\n }\n }\n }\n\n /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.\n function forceSafeTransferETH(address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n if lt(selfbalance(), amount) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, to) // Store the address in scratch space.\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\n }\n }\n }\n\n /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.\n function forceSafeTransferAllETH(address to) internal {\n /// @solidity memory-safe-assembly\n assembly {\n // forgefmt: disable-next-item\n if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, to) // Store the address in scratch space.\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\n }\n }\n }\n\n /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\n function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)\n internal\n returns (bool success)\n {\n /// @solidity memory-safe-assembly\n assembly {\n success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)\n }\n }\n\n /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.\n function trySafeTransferAllETH(address to, uint256 gasStipend)\n internal\n returns (bool success)\n {\n /// @solidity memory-safe-assembly\n assembly {\n success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* ERC20 OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\n /// Reverts upon failure.\n ///\n /// The `from` account must have at least `amount` approved for\n /// the current contract to manage.\n function safeTransferFrom(address token, address from, address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, amount) // Store the `amount` argument.\n mstore(0x40, to) // Store the `to` argument.\n mstore(0x2c, shl(96, from)) // Store the `from` argument.\n mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.\n // Perform the transfer, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\n )\n ) {\n mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x60, 0) // Restore the zero slot to zero.\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\n ///\n /// The `from` account must have at least `amount` approved for the current contract to manage.\n function trySafeTransferFrom(address token, address from, address to, uint256 amount)\n internal\n returns (bool success)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, amount) // Store the `amount` argument.\n mstore(0x40, to) // Store the `to` argument.\n mstore(0x2c, shl(96, from)) // Store the `from` argument.\n mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.\n success :=\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\n )\n mstore(0x60, 0) // Restore the zero slot to zero.\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Sends all of ERC20 `token` from `from` to `to`.\n /// Reverts upon failure.\n ///\n /// The `from` account must have their entire balance approved for the current contract to manage.\n function safeTransferAllFrom(address token, address from, address to)\n internal\n returns (uint256 amount)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x40, to) // Store the `to` argument.\n mstore(0x2c, shl(96, from)) // Store the `from` argument.\n mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.\n // Read the balance, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)\n )\n ) {\n mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.\n amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.\n // Perform the transfer, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\n )\n ) {\n mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x60, 0) // Restore the zero slot to zero.\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.\n /// Reverts upon failure.\n function safeTransfer(address token, address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x14, to) // Store the `to` argument.\n mstore(0x34, amount) // Store the `amount` argument.\n mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.\n // Perform the transfer, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n )\n ) {\n mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\n }\n }\n\n /// @dev Sends all of ERC20 `token` from the current contract to `to`.\n /// Reverts upon failure.\n function safeTransferAll(address token, address to) internal returns (uint256 amount) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.\n mstore(0x20, address()) // Store the address of the current contract.\n // Read the balance, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)\n )\n ) {\n mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x14, to) // Store the `to` argument.\n amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.\n mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.\n // Perform the transfer, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n )\n ) {\n mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\n }\n }\n\n /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.\n /// Reverts upon failure.\n function safeApprove(address token, address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x14, to) // Store the `to` argument.\n mstore(0x34, amount) // Store the `amount` argument.\n mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\n // Perform the approval, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n )\n ) {\n mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\n }\n }\n\n /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.\n /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,\n /// then retries the approval again (some tokens, e.g. USDT, requires this).\n /// Reverts upon failure.\n function safeApproveWithRetry(address token, address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x14, to) // Store the `to` argument.\n mstore(0x34, amount) // Store the `amount` argument.\n mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\n // Perform the approval, retrying upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n )\n ) {\n mstore(0x34, 0) // Store 0 for the `amount`.\n mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\n pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval.\n mstore(0x34, amount) // Store back the original `amount`.\n // Retry the approval, reverting upon failure.\n if iszero(\n and(\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n )\n ) {\n mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.\n revert(0x1c, 0x04)\n }\n }\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\n }\n }\n\n /// @dev Returns the amount of ERC20 `token` owned by `account`.\n /// Returns zero if the `token` does not exist.\n function balanceOf(address token, address account) internal view returns (uint256 amount) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x14, account) // Store the `account` argument.\n mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.\n amount :=\n mul( // The arguments of `mul` are evaluated from right to left.\n mload(0x20),\n and( // The arguments of `and` are evaluated from right to left.\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)\n )\n )\n }\n }\n\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\n /// If the initial attempt fails, try to use Permit2 to transfer the token.\n /// Reverts upon failure.\n ///\n /// The `from` account must have at least `amount` approved for the current contract to manage.\n function safeTransferFrom2(address token, address from, address to, uint256 amount) internal {\n if (!trySafeTransferFrom(token, from, to, amount)) {\n permit2TransferFrom(token, from, to, amount);\n }\n }\n\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to` via Permit2.\n /// Reverts upon failure.\n function permit2TransferFrom(address token, address from, address to, uint256 amount)\n internal\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n mstore(add(m, 0x74), shr(96, shl(96, token)))\n mstore(add(m, 0x54), amount)\n mstore(add(m, 0x34), to)\n mstore(add(m, 0x20), shl(96, from))\n // `transferFrom(address,address,uint160,address)`.\n mstore(m, 0x36c78516000000000000000000000000)\n let p := PERMIT2\n let exists := eq(chainid(), 1)\n if iszero(exists) { exists := iszero(iszero(extcodesize(p))) }\n if iszero(and(call(gas(), p, 0, add(m, 0x10), 0x84, codesize(), 0x00), exists)) {\n mstore(0x00, 0x7939f4248757f0fd) // `TransferFromFailed()` or `Permit2AmountOverflow()`.\n revert(add(0x18, shl(2, iszero(iszero(shr(160, amount))))), 0x04)\n }\n }\n }\n\n /// @dev Permit a user to spend a given amount of\n /// another user's tokens via native EIP-2612 permit if possible, falling\n /// back to Permit2 if native permit fails or is not implemented on the token.\n function permit2(\n address token,\n address owner,\n address spender,\n uint256 amount,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n bool success;\n /// @solidity memory-safe-assembly\n assembly {\n for {} shl(96, xor(token, WETH9)) {} {\n mstore(0x00, 0x3644e515) // `DOMAIN_SEPARATOR()`.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n lt(iszero(mload(0x00)), eq(returndatasize(), 0x20)), // Returns 1 non-zero word.\n // Gas stipend to limit gas burn for tokens that don't refund gas when\n // an non-existing function is called. 5K should be enough for a SLOAD.\n staticcall(5000, token, 0x1c, 0x04, 0x00, 0x20)\n )\n ) { break }\n // After here, we can be sure that token is a contract.\n let m := mload(0x40)\n mstore(add(m, 0x34), spender)\n mstore(add(m, 0x20), shl(96, owner))\n mstore(add(m, 0x74), deadline)\n if eq(mload(0x00), DAI_DOMAIN_SEPARATOR) {\n mstore(0x14, owner)\n mstore(0x00, 0x7ecebe00000000000000000000000000) // `nonces(address)`.\n mstore(add(m, 0x94), staticcall(gas(), token, 0x10, 0x24, add(m, 0x54), 0x20))\n mstore(m, 0x8fcbaf0c000000000000000000000000) // `IDAIPermit.permit`.\n // `nonces` is already at `add(m, 0x54)`.\n // `1` is already stored at `add(m, 0x94)`.\n mstore(add(m, 0xb4), and(0xff, v))\n mstore(add(m, 0xd4), r)\n mstore(add(m, 0xf4), s)\n success := call(gas(), token, 0, add(m, 0x10), 0x104, codesize(), 0x00)\n break\n }\n mstore(m, 0xd505accf000000000000000000000000) // `IERC20Permit.permit`.\n mstore(add(m, 0x54), amount)\n mstore(add(m, 0x94), and(0xff, v))\n mstore(add(m, 0xb4), r)\n mstore(add(m, 0xd4), s)\n success := call(gas(), token, 0, add(m, 0x10), 0xe4, codesize(), 0x00)\n break\n }\n }\n if (!success) simplePermit2(token, owner, spender, amount, deadline, v, r, s);\n }\n\n /// @dev Simple permit on the Permit2 contract.\n function simplePermit2(\n address token,\n address owner,\n address spender,\n uint256 amount,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n mstore(m, 0x927da105) // `allowance(address,address,address)`.\n {\n let addressMask := shr(96, not(0))\n mstore(add(m, 0x20), and(addressMask, owner))\n mstore(add(m, 0x40), and(addressMask, token))\n mstore(add(m, 0x60), and(addressMask, spender))\n mstore(add(m, 0xc0), and(addressMask, spender))\n }\n let p := mul(PERMIT2, iszero(shr(160, amount)))\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n gt(returndatasize(), 0x5f), // Returns 3 words: `amount`, `expiration`, `nonce`.\n staticcall(gas(), p, add(m, 0x1c), 0x64, add(m, 0x60), 0x60)\n )\n ) {\n mstore(0x00, 0x6b836e6b8757f0fd) // `Permit2Failed()` or `Permit2AmountOverflow()`.\n revert(add(0x18, shl(2, iszero(p))), 0x04)\n }\n mstore(m, 0x2b67b570) // `Permit2.permit` (PermitSingle variant).\n // `owner` is already `add(m, 0x20)`.\n // `token` is already at `add(m, 0x40)`.\n mstore(add(m, 0x60), amount)\n mstore(add(m, 0x80), 0xffffffffffff) // `expiration = type(uint48).max`.\n // `nonce` is already at `add(m, 0xa0)`.\n // `spender` is already at `add(m, 0xc0)`.\n mstore(add(m, 0xe0), deadline)\n mstore(add(m, 0x100), 0x100) // `signature` offset.\n mstore(add(m, 0x120), 0x41) // `signature` length.\n mstore(add(m, 0x140), r)\n mstore(add(m, 0x160), s)\n mstore(add(m, 0x180), shl(248, v))\n if iszero(call(gas(), p, 0, add(m, 0x1c), 0x184, codesize(), 0x00)) {\n mstore(0x00, 0x6b836e6b) // `Permit2Failed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n}\n" + }, + "lib/solady/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Simple ERC20 + EIP-2612 implementation.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)\n///\n/// @dev Note:\n/// - The ERC20 standard allows minting and transferring to and from the zero address,\n/// minting and transferring zero tokens, as well as self-approvals.\n/// For performance, this implementation WILL NOT revert for such actions.\n/// Please add any checks with overrides if desired.\n/// - The `permit` function uses the ecrecover precompile (0x1).\n///\n/// If you are overriding:\n/// - NEVER violate the ERC20 invariant:\n/// the total sum of all balances must be equal to `totalSupply()`.\n/// - Check that the overridden function is actually used in the function you want to\n/// change the behavior of. Much of the code has been manually inlined for performance.\nabstract contract ERC20 {\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CUSTOM ERRORS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev The total supply has overflowed.\n error TotalSupplyOverflow();\n\n /// @dev The allowance has overflowed.\n error AllowanceOverflow();\n\n /// @dev The allowance has underflowed.\n error AllowanceUnderflow();\n\n /// @dev Insufficient balance.\n error InsufficientBalance();\n\n /// @dev Insufficient allowance.\n error InsufficientAllowance();\n\n /// @dev The permit is invalid.\n error InvalidPermit();\n\n /// @dev The permit has expired.\n error PermitExpired();\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* EVENTS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Emitted when `amount` tokens is transferred from `from` to `to`.\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /// @dev Emitted when `amount` tokens is approved by `owner` to be used by `spender`.\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /// @dev `keccak256(bytes(\"Transfer(address,address,uint256)\"))`.\n uint256 private constant _TRANSFER_EVENT_SIGNATURE =\n 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;\n\n /// @dev `keccak256(bytes(\"Approval(address,address,uint256)\"))`.\n uint256 private constant _APPROVAL_EVENT_SIGNATURE =\n 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* STORAGE */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev The storage slot for the total supply.\n uint256 private constant _TOTAL_SUPPLY_SLOT = 0x05345cdf77eb68f44c;\n\n /// @dev The balance slot of `owner` is given by:\n /// ```\n /// mstore(0x0c, _BALANCE_SLOT_SEED)\n /// mstore(0x00, owner)\n /// let balanceSlot := keccak256(0x0c, 0x20)\n /// ```\n uint256 private constant _BALANCE_SLOT_SEED = 0x87a211a2;\n\n /// @dev The allowance slot of (`owner`, `spender`) is given by:\n /// ```\n /// mstore(0x20, spender)\n /// mstore(0x0c, _ALLOWANCE_SLOT_SEED)\n /// mstore(0x00, owner)\n /// let allowanceSlot := keccak256(0x0c, 0x34)\n /// ```\n uint256 private constant _ALLOWANCE_SLOT_SEED = 0x7f5e9f20;\n\n /// @dev The nonce slot of `owner` is given by:\n /// ```\n /// mstore(0x0c, _NONCES_SLOT_SEED)\n /// mstore(0x00, owner)\n /// let nonceSlot := keccak256(0x0c, 0x20)\n /// ```\n uint256 private constant _NONCES_SLOT_SEED = 0x38377508;\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CONSTANTS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev `(_NONCES_SLOT_SEED << 16) | 0x1901`.\n uint256 private constant _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX = 0x383775081901;\n\n /// @dev `keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\")`.\n bytes32 private constant _DOMAIN_TYPEHASH =\n 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;\n\n /// @dev `keccak256(\"1\")`.\n bytes32 private constant _VERSION_HASH =\n 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6;\n\n /// @dev `keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\")`.\n bytes32 private constant _PERMIT_TYPEHASH =\n 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* ERC20 METADATA */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Returns the name of the token.\n function name() public view virtual returns (string memory);\n\n /// @dev Returns the symbol of the token.\n function symbol() public view virtual returns (string memory);\n\n /// @dev Returns the decimals places of the token.\n function decimals() public view virtual returns (uint8) {\n return 18;\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* ERC20 */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Returns the amount of tokens in existence.\n function totalSupply() public view virtual returns (uint256 result) {\n /// @solidity memory-safe-assembly\n assembly {\n result := sload(_TOTAL_SUPPLY_SLOT)\n }\n }\n\n /// @dev Returns the amount of tokens owned by `owner`.\n function balanceOf(address owner) public view virtual returns (uint256 result) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x0c, _BALANCE_SLOT_SEED)\n mstore(0x00, owner)\n result := sload(keccak256(0x0c, 0x20))\n }\n }\n\n /// @dev Returns the amount of tokens that `spender` can spend on behalf of `owner`.\n function allowance(address owner, address spender)\n public\n view\n virtual\n returns (uint256 result)\n {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x20, spender)\n mstore(0x0c, _ALLOWANCE_SLOT_SEED)\n mstore(0x00, owner)\n result := sload(keccak256(0x0c, 0x34))\n }\n }\n\n /// @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n ///\n /// Emits a {Approval} event.\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the allowance slot and store the amount.\n mstore(0x20, spender)\n mstore(0x0c, _ALLOWANCE_SLOT_SEED)\n mstore(0x00, caller())\n sstore(keccak256(0x0c, 0x34), amount)\n // Emit the {Approval} event.\n mstore(0x00, amount)\n log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, caller(), shr(96, mload(0x2c)))\n }\n return true;\n }\n\n /// @dev Transfer `amount` tokens from the caller to `to`.\n ///\n /// Requirements:\n /// - `from` must at least have `amount`.\n ///\n /// Emits a {Transfer} event.\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n _beforeTokenTransfer(msg.sender, to, amount);\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the balance slot and load its value.\n mstore(0x0c, _BALANCE_SLOT_SEED)\n mstore(0x00, caller())\n let fromBalanceSlot := keccak256(0x0c, 0x20)\n let fromBalance := sload(fromBalanceSlot)\n // Revert if insufficient balance.\n if gt(amount, fromBalance) {\n mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated balance.\n sstore(fromBalanceSlot, sub(fromBalance, amount))\n // Compute the balance slot of `to`.\n mstore(0x00, to)\n let toBalanceSlot := keccak256(0x0c, 0x20)\n // Add and store the updated balance of `to`.\n // Will not overflow because the sum of all user balances\n // cannot exceed the maximum uint256 value.\n sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))\n // Emit the {Transfer} event.\n mstore(0x20, amount)\n log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, caller(), shr(96, mload(0x0c)))\n }\n _afterTokenTransfer(msg.sender, to, amount);\n return true;\n }\n\n /// @dev Transfers `amount` tokens from `from` to `to`.\n ///\n /// Note: Does not update the allowance if it is the maximum uint256 value.\n ///\n /// Requirements:\n /// - `from` must at least have `amount`.\n /// - The caller must have at least `amount` of allowance to transfer the tokens of `from`.\n ///\n /// Emits a {Transfer} event.\n function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {\n _beforeTokenTransfer(from, to, amount);\n /// @solidity memory-safe-assembly\n assembly {\n let from_ := shl(96, from)\n // Compute the allowance slot and load its value.\n mstore(0x20, caller())\n mstore(0x0c, or(from_, _ALLOWANCE_SLOT_SEED))\n let allowanceSlot := keccak256(0x0c, 0x34)\n let allowance_ := sload(allowanceSlot)\n // If the allowance is not the maximum uint256 value.\n if add(allowance_, 1) {\n // Revert if the amount to be transferred exceeds the allowance.\n if gt(amount, allowance_) {\n mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated allowance.\n sstore(allowanceSlot, sub(allowance_, amount))\n }\n // Compute the balance slot and load its value.\n mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))\n let fromBalanceSlot := keccak256(0x0c, 0x20)\n let fromBalance := sload(fromBalanceSlot)\n // Revert if insufficient balance.\n if gt(amount, fromBalance) {\n mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated balance.\n sstore(fromBalanceSlot, sub(fromBalance, amount))\n // Compute the balance slot of `to`.\n mstore(0x00, to)\n let toBalanceSlot := keccak256(0x0c, 0x20)\n // Add and store the updated balance of `to`.\n // Will not overflow because the sum of all user balances\n // cannot exceed the maximum uint256 value.\n sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))\n // Emit the {Transfer} event.\n mstore(0x20, amount)\n log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))\n }\n _afterTokenTransfer(from, to, amount);\n return true;\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* EIP-2612 */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev For more performance, override to return the constant value\n /// of `keccak256(bytes(name()))` if `name()` will never change.\n function _constantNameHash() internal view virtual returns (bytes32 result) {}\n\n /// @dev Returns the current nonce for `owner`.\n /// This value is used to compute the signature for EIP-2612 permit.\n function nonces(address owner) public view virtual returns (uint256 result) {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the nonce slot and load its value.\n mstore(0x0c, _NONCES_SLOT_SEED)\n mstore(0x00, owner)\n result := sload(keccak256(0x0c, 0x20))\n }\n }\n\n /// @dev Sets `value` as the allowance of `spender` over the tokens of `owner`,\n /// authorized by a signed approval by `owner`.\n ///\n /// Emits a {Approval} event.\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 ) public virtual {\n bytes32 nameHash = _constantNameHash();\n // We simply calculate it on-the-fly to allow for cases where the `name` may change.\n if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));\n /// @solidity memory-safe-assembly\n assembly {\n // Revert if the block timestamp is greater than `deadline`.\n if gt(timestamp(), deadline) {\n mstore(0x00, 0x1a15a3cc) // `PermitExpired()`.\n revert(0x1c, 0x04)\n }\n let m := mload(0x40) // Grab the free memory pointer.\n // Clean the upper 96 bits.\n owner := shr(96, shl(96, owner))\n spender := shr(96, shl(96, spender))\n // Compute the nonce slot and load its value.\n mstore(0x0e, _NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX)\n mstore(0x00, owner)\n let nonceSlot := keccak256(0x0c, 0x20)\n let nonceValue := sload(nonceSlot)\n // Prepare the domain separator.\n mstore(m, _DOMAIN_TYPEHASH)\n mstore(add(m, 0x20), nameHash)\n mstore(add(m, 0x40), _VERSION_HASH)\n mstore(add(m, 0x60), chainid())\n mstore(add(m, 0x80), address())\n mstore(0x2e, keccak256(m, 0xa0))\n // Prepare the struct hash.\n mstore(m, _PERMIT_TYPEHASH)\n mstore(add(m, 0x20), owner)\n mstore(add(m, 0x40), spender)\n mstore(add(m, 0x60), value)\n mstore(add(m, 0x80), nonceValue)\n mstore(add(m, 0xa0), deadline)\n mstore(0x4e, keccak256(m, 0xc0))\n // Prepare the ecrecover calldata.\n mstore(0x00, keccak256(0x2c, 0x42))\n mstore(0x20, and(0xff, v))\n mstore(0x40, r)\n mstore(0x60, s)\n let t := staticcall(gas(), 1, 0, 0x80, 0x20, 0x20)\n // If the ecrecover fails, the returndatasize will be 0x00,\n // `owner` will be checked if it equals the hash at 0x00,\n // which evaluates to false (i.e. 0), and we will revert.\n // If the ecrecover succeeds, the returndatasize will be 0x20,\n // `owner` will be compared against the returned address at 0x20.\n if iszero(eq(mload(returndatasize()), owner)) {\n mstore(0x00, 0xddafbaef) // `InvalidPermit()`.\n revert(0x1c, 0x04)\n }\n // Increment and store the updated nonce.\n sstore(nonceSlot, add(nonceValue, t)) // `t` is 1 if ecrecover succeeds.\n // Compute the allowance slot and store the value.\n // The `owner` is already at slot 0x20.\n mstore(0x40, or(shl(160, _ALLOWANCE_SLOT_SEED), spender))\n sstore(keccak256(0x2c, 0x34), value)\n // Emit the {Approval} event.\n log3(add(m, 0x60), 0x20, _APPROVAL_EVENT_SIGNATURE, owner, spender)\n mstore(0x40, m) // Restore the free memory pointer.\n mstore(0x60, 0) // Restore the zero pointer.\n }\n }\n\n /// @dev Returns the EIP-712 domain separator for the EIP-2612 permit.\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) {\n bytes32 nameHash = _constantNameHash();\n // We simply calculate it on-the-fly to allow for cases where the `name` may change.\n if (nameHash == bytes32(0)) nameHash = keccak256(bytes(name()));\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Grab the free memory pointer.\n mstore(m, _DOMAIN_TYPEHASH)\n mstore(add(m, 0x20), nameHash)\n mstore(add(m, 0x40), _VERSION_HASH)\n mstore(add(m, 0x60), chainid())\n mstore(add(m, 0x80), address())\n result := keccak256(m, 0xa0)\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* INTERNAL MINT FUNCTIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Mints `amount` tokens to `to`, increasing the total supply.\n ///\n /// Emits a {Transfer} event.\n function _mint(address to, uint256 amount) internal virtual {\n _beforeTokenTransfer(address(0), to, amount);\n /// @solidity memory-safe-assembly\n assembly {\n let totalSupplyBefore := sload(_TOTAL_SUPPLY_SLOT)\n let totalSupplyAfter := add(totalSupplyBefore, amount)\n // Revert if the total supply overflows.\n if lt(totalSupplyAfter, totalSupplyBefore) {\n mstore(0x00, 0xe5cfe957) // `TotalSupplyOverflow()`.\n revert(0x1c, 0x04)\n }\n // Store the updated total supply.\n sstore(_TOTAL_SUPPLY_SLOT, totalSupplyAfter)\n // Compute the balance slot and load its value.\n mstore(0x0c, _BALANCE_SLOT_SEED)\n mstore(0x00, to)\n let toBalanceSlot := keccak256(0x0c, 0x20)\n // Add and store the updated balance.\n sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))\n // Emit the {Transfer} event.\n mstore(0x20, amount)\n log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, 0, shr(96, mload(0x0c)))\n }\n _afterTokenTransfer(address(0), to, amount);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* INTERNAL BURN FUNCTIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Burns `amount` tokens from `from`, reducing the total supply.\n ///\n /// Emits a {Transfer} event.\n function _burn(address from, uint256 amount) internal virtual {\n _beforeTokenTransfer(from, address(0), amount);\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the balance slot and load its value.\n mstore(0x0c, _BALANCE_SLOT_SEED)\n mstore(0x00, from)\n let fromBalanceSlot := keccak256(0x0c, 0x20)\n let fromBalance := sload(fromBalanceSlot)\n // Revert if insufficient balance.\n if gt(amount, fromBalance) {\n mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated balance.\n sstore(fromBalanceSlot, sub(fromBalance, amount))\n // Subtract and store the updated total supply.\n sstore(_TOTAL_SUPPLY_SLOT, sub(sload(_TOTAL_SUPPLY_SLOT), amount))\n // Emit the {Transfer} event.\n mstore(0x00, amount)\n log3(0x00, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, shl(96, from)), 0)\n }\n _afterTokenTransfer(from, address(0), amount);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* INTERNAL TRANSFER FUNCTIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Moves `amount` of tokens from `from` to `to`.\n function _transfer(address from, address to, uint256 amount) internal virtual {\n _beforeTokenTransfer(from, to, amount);\n /// @solidity memory-safe-assembly\n assembly {\n let from_ := shl(96, from)\n // Compute the balance slot and load its value.\n mstore(0x0c, or(from_, _BALANCE_SLOT_SEED))\n let fromBalanceSlot := keccak256(0x0c, 0x20)\n let fromBalance := sload(fromBalanceSlot)\n // Revert if insufficient balance.\n if gt(amount, fromBalance) {\n mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated balance.\n sstore(fromBalanceSlot, sub(fromBalance, amount))\n // Compute the balance slot of `to`.\n mstore(0x00, to)\n let toBalanceSlot := keccak256(0x0c, 0x20)\n // Add and store the updated balance of `to`.\n // Will not overflow because the sum of all user balances\n // cannot exceed the maximum uint256 value.\n sstore(toBalanceSlot, add(sload(toBalanceSlot), amount))\n // Emit the {Transfer} event.\n mstore(0x20, amount)\n log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c)))\n }\n _afterTokenTransfer(from, to, amount);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* INTERNAL ALLOWANCE FUNCTIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Updates the allowance of `owner` for `spender` based on spent `amount`.\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the allowance slot and load its value.\n mstore(0x20, spender)\n mstore(0x0c, _ALLOWANCE_SLOT_SEED)\n mstore(0x00, owner)\n let allowanceSlot := keccak256(0x0c, 0x34)\n let allowance_ := sload(allowanceSlot)\n // If the allowance is not the maximum uint256 value.\n if add(allowance_, 1) {\n // Revert if the amount to be transferred exceeds the allowance.\n if gt(amount, allowance_) {\n mstore(0x00, 0x13be252b) // `InsufficientAllowance()`.\n revert(0x1c, 0x04)\n }\n // Subtract and store the updated allowance.\n sstore(allowanceSlot, sub(allowance_, amount))\n }\n }\n }\n\n /// @dev Sets `amount` as the allowance of `spender` over the tokens of `owner`.\n ///\n /// Emits a {Approval} event.\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n /// @solidity memory-safe-assembly\n assembly {\n let owner_ := shl(96, owner)\n // Compute the allowance slot and store the amount.\n mstore(0x20, spender)\n mstore(0x0c, or(owner_, _ALLOWANCE_SLOT_SEED))\n sstore(keccak256(0x0c, 0x34), amount)\n // Emit the {Approval} event.\n mstore(0x00, amount)\n log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, shr(96, owner_), shr(96, mload(0x2c)))\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* HOOKS TO OVERRIDE */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Hook that is called before any transfer of tokens.\n /// This includes minting and burning.\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /// @dev Hook that is called after any transfer of tokens.\n /// This includes minting and burning.\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n LibUtil.revertWith(res);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n\n function revertWith(bytes memory data) internal pure {\n assembly {\n let dataSize := mload(data) // Load the size of the data\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\n revert(dataPtr, dataSize) // Revert with the given data\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "solady/=lib/solady/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +1.0.1 + Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... -AcrossFacetPackedV3 +0x21a786957c69424a4353afe743242bd9db3cc07b +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/AcrossFacetPackedV3.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport { IAcrossSpokePool } from \\\"../Interfaces/IAcrossSpokePool.sol\\\";\\nimport { TransferrableOwnership } from \\\"../Helpers/TransferrableOwnership.sol\\\";\\nimport { AcrossFacetV3 } from \\\"./AcrossFacetV3.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { ERC20, SafeTransferLib } from \\\"solmate/utils/SafeTransferLib.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\n\\n/// @title AcrossFacetPackedV3\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Across in a gas-optimized way\\n/// @custom:version 1.2.0\\ncontract AcrossFacetPackedV3 is ILiFi, TransferrableOwnership {\\n using SafeTransferLib for ERC20;\\n\\n /// Storage ///\\n\\n /// @notice The contract address of the cbridge on the source chain.\\n IAcrossSpokePool public immutable spokePool;\\n\\n /// @notice The WETH address on the current chain.\\n address public immutable wrappedNative;\\n\\n /// Events ///\\n\\n event LiFiAcrossTransfer(bytes8 _transactionId);\\n event CallExecutedAndFundsWithdrawn();\\n\\n /// Errors ///\\n\\n error WithdrawFailed();\\n\\n // using this struct to bundle parameters is required since otherwise we run into stack-too-deep errors\\n // (Solidity can only handle a limited amount of parameters at any given time)\\n struct PackedParameters {\\n bytes32 transactionId;\\n address receiver;\\n address depositor;\\n uint64 destinationChainId;\\n address receivingAssetId;\\n uint256 outputAmount;\\n address exclusiveRelayer;\\n uint32 quoteTimestamp;\\n uint32 fillDeadline;\\n uint32 exclusivityDeadline;\\n bytes message;\\n }\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract\\n /// @param _spokePool The contract address of the spoke pool on the source chain\\n /// @param _wrappedNative The address of the wrapped native token on the source chain\\n /// @param _owner The address of the contract owner\\n constructor(\\n IAcrossSpokePool _spokePool,\\n address _wrappedNative,\\n address _owner\\n ) TransferrableOwnership(_owner) {\\n spokePool = _spokePool;\\n wrappedNative = _wrappedNative;\\n }\\n\\n /// External Methods ///\\n\\n /// @dev Only meant to be called outside of the context of the diamond\\n /// @notice Sets approval for the Across spoke pool Router to spend the specified token\\n /// @param tokensToApprove The tokens to approve to the Across spoke pool\\n function setApprovalForBridge(\\n address[] calldata tokensToApprove\\n ) external onlyOwner {\\n for (uint256 i; i < tokensToApprove.length; i++) {\\n // Give Across spoke pool approval to pull tokens from this facet\\n LibAsset.maxApproveERC20(\\n IERC20(tokensToApprove[i]),\\n address(spokePool),\\n type(uint256).max\\n );\\n }\\n }\\n\\n /// @notice Bridges native tokens via Across (packed implementation)\\n /// @dev Calldata mapping:\\n /// [0:4] - function selector\\n /// [4:12] - transactionId\\n /// [12:32] - receiver\\n /// [32:52] - depositor\\n /// [52:56] - destinationChainId\\n /// [56:76] - receivingAssetId\\n /// [76:108] - outputAmount\\n /// [108:128] - exclusiveRelayer\\n /// [128:132] - quoteTimestamp\\n /// [132:136] - fillDeadline\\n /// [136:140] - exclusivityDeadline\\n /// [140:] - message\\n function startBridgeTokensViaAcrossV3NativePacked() external payable {\\n // call Across spoke pool to bridge assets\\n spokePool.depositV3{ value: msg.value }(\\n address(bytes20(msg.data[32:52])), // depositor\\n address(bytes20(msg.data[12:32])), // recipient\\n wrappedNative, // inputToken\\n address(bytes20(msg.data[56:76])), // outputToken\\n msg.value, // inputAmount\\n uint256(bytes32(msg.data[76:108])), // outputAmount\\n uint64(uint32(bytes4(msg.data[52:56]))), // destinationChainId\\n address(bytes20(msg.data[108:128])), // exclusiveRelayer\\n uint32(bytes4(msg.data[128:132])), // quoteTimestamp\\n uint32(bytes4(msg.data[132:136])), // fillDeadline\\n uint32(bytes4(msg.data[136:140])), // exclusivityDeadline\\n msg.data[140:msg.data.length]\\n );\\n\\n emit LiFiAcrossTransfer(bytes8(msg.data[4:12]));\\n }\\n\\n /// @notice Bridges native tokens via Across (minimal implementation)\\n /// @param _parameters Contains all parameters required for native bridging with AcrossV3\\n function startBridgeTokensViaAcrossV3NativeMin(\\n PackedParameters calldata _parameters\\n ) external payable {\\n // call Across spoke pool to bridge assets\\n spokePool.depositV3{ value: msg.value }(\\n _parameters.depositor, // depositor\\n _parameters.receiver,\\n wrappedNative, // inputToken\\n _parameters.receivingAssetId, // outputToken\\n msg.value, // inputAmount\\n _parameters.outputAmount,\\n _parameters.destinationChainId,\\n _parameters.exclusiveRelayer,\\n _parameters.quoteTimestamp,\\n _parameters.fillDeadline,\\n _parameters.exclusivityDeadline,\\n _parameters.message\\n );\\n\\n emit LiFiAcrossTransfer(bytes8(_parameters.transactionId));\\n }\\n\\n /// @notice Bridges ERC20 tokens via Across (packed implementation)\\n /// @dev Calldata mapping:\\n /// [0:4] - function selector\\n /// [4:12] - transactionId\\n /// [12:32] - receiver\\n /// [32:52] - depositor\\n /// [52:72] - sendingAssetId\\n /// [72:88] - inputAmount\\n /// [88:92] - destinationChainId\\n /// [92:112] - receivingAssetId\\n /// [112:144] - outputAmount\\n /// [144:164] - exclusiveRelayer\\n /// [164:168] - quoteTimestamp\\n /// [168:172] - fillDeadline\\n /// [172:176] - exclusivityDeadline\\n /// [176:] - message\\n function startBridgeTokensViaAcrossV3ERC20Packed() external {\\n address sendingAssetId = address(bytes20(msg.data[52:72]));\\n uint256 inputAmount = uint256(uint128(bytes16(msg.data[72:88])));\\n\\n ERC20(sendingAssetId).safeTransferFrom(\\n msg.sender,\\n address(this),\\n inputAmount\\n );\\n\\n spokePool.depositV3(\\n address(bytes20(msg.data[32:52])), // depositor\\n address(bytes20(msg.data[12:32])), // recipient\\n sendingAssetId, // inputToken\\n address(bytes20(msg.data[92:112])), // outputToken\\n inputAmount, // inputAmount\\n uint256(bytes32(msg.data[112:144])), // outputAmount\\n uint64(uint32(bytes4(msg.data[88:92]))), // destinationChainId\\n address(bytes20(msg.data[144:164])), // exclusiveRelayer\\n uint32(bytes4(msg.data[164:168])), // quoteTimestamp\\n uint32(bytes4(msg.data[168:172])), // fillDeadline\\n uint32(bytes4(msg.data[172:176])), // exclusivityDeadline\\n msg.data[176:msg.data.length]\\n );\\n\\n emit LiFiAcrossTransfer(bytes8(msg.data[4:12]));\\n }\\n\\n /// @notice Bridges ERC20 tokens via Across (minimal implementation)\\n /// @param _parameters Contains all base parameters required for bridging with AcrossV3\\n /// @param sendingAssetId The address of the asset/token to be bridged\\n /// @param inputAmount The amount to be bridged (including fees)\\n function startBridgeTokensViaAcrossV3ERC20Min(\\n PackedParameters calldata _parameters,\\n address sendingAssetId,\\n uint256 inputAmount\\n ) external {\\n // Deposit assets\\n ERC20(sendingAssetId).safeTransferFrom(\\n msg.sender,\\n address(this),\\n inputAmount\\n );\\n\\n // call Across SpokePool\\n spokePool.depositV3(\\n _parameters.depositor, // depositor\\n _parameters.receiver,\\n sendingAssetId, // inputToken\\n _parameters.receivingAssetId, // outputToken\\n inputAmount,\\n _parameters.outputAmount,\\n _parameters.destinationChainId,\\n _parameters.exclusiveRelayer,\\n _parameters.quoteTimestamp,\\n _parameters.fillDeadline,\\n _parameters.exclusivityDeadline,\\n _parameters.message\\n );\\n\\n emit LiFiAcrossTransfer(bytes8(_parameters.transactionId));\\n }\\n\\n /// @notice Encodes calldata that can be used to call the native 'packed' function\\n /// @param _parameters Contains all parameters required for native bridging with AcrossV3\\n function encode_startBridgeTokensViaAcrossV3NativePacked(\\n PackedParameters calldata _parameters\\n ) external pure returns (bytes memory) {\\n // there are already existing networks with chainIds outside uint32 range but since we not support either of them yet,\\n // we feel comfortable using this approach to save further gas\\n require(\\n _parameters.destinationChainId <= type(uint32).max,\\n \\\"destinationChainId value passed too big to fit in uint32\\\"\\n );\\n\\n return\\n bytes.concat(\\n AcrossFacetPackedV3\\n .startBridgeTokensViaAcrossV3NativePacked\\n .selector,\\n bytes8(_parameters.transactionId),\\n bytes20(_parameters.receiver),\\n bytes20(_parameters.depositor),\\n bytes4(uint32(_parameters.destinationChainId)),\\n bytes20(_parameters.receivingAssetId),\\n bytes32(_parameters.outputAmount),\\n bytes20(_parameters.exclusiveRelayer),\\n bytes4(_parameters.quoteTimestamp),\\n bytes4(_parameters.fillDeadline),\\n bytes4(_parameters.exclusivityDeadline),\\n _parameters.message\\n );\\n }\\n\\n /// @notice Encodes calldata that can be used to call the ERC20 'packed' function\\n /// @param _parameters Contains all base parameters required for bridging with AcrossV3\\n /// @param sendingAssetId The address of the asset/token to be bridged\\n /// @param inputAmount The amount to be bridged (including fees)\\n function encode_startBridgeTokensViaAcrossV3ERC20Packed(\\n PackedParameters calldata _parameters,\\n address sendingAssetId,\\n uint256 inputAmount\\n ) external pure returns (bytes memory) {\\n // there are already existing networks with chainIds outside uint32 range but since we not support either of them yet,\\n // we feel comfortable using this approach to save further gas\\n require(\\n _parameters.destinationChainId <= type(uint32).max,\\n \\\"destinationChainId value passed too big to fit in uint32\\\"\\n );\\n\\n require(\\n inputAmount <= type(uint128).max,\\n \\\"inputAmount value passed too big to fit in uint128\\\"\\n );\\n\\n // Split the concatenation into parts to avoid \\\"stack too deep\\\" errors\\n bytes memory part1 = bytes.concat(\\n AcrossFacetPackedV3\\n .startBridgeTokensViaAcrossV3ERC20Packed\\n .selector,\\n bytes8(_parameters.transactionId),\\n bytes20(_parameters.receiver),\\n bytes20(_parameters.depositor),\\n bytes20(sendingAssetId)\\n );\\n\\n bytes memory part2 = bytes.concat(\\n bytes16(uint128(inputAmount)),\\n bytes4(uint32(_parameters.destinationChainId)),\\n bytes20(_parameters.receivingAssetId),\\n bytes32(_parameters.outputAmount)\\n );\\n\\n bytes memory part3 = bytes.concat(\\n bytes20(_parameters.exclusiveRelayer),\\n bytes4(_parameters.quoteTimestamp),\\n bytes4(_parameters.fillDeadline),\\n bytes4(_parameters.exclusivityDeadline)\\n );\\n\\n // Combine all parts with the message\\n return bytes.concat(part1, part2, part3, _parameters.message);\\n }\\n\\n /// @notice Decodes calldata that is meant to be used for calling the native 'packed' function\\n /// @param data the calldata to be decoded\\n function decode_startBridgeTokensViaAcrossV3NativePacked(\\n bytes calldata data\\n )\\n external\\n pure\\n returns (\\n BridgeData memory bridgeData,\\n AcrossFacetV3.AcrossV3Data memory acrossData\\n )\\n {\\n require(\\n data.length >= 140,\\n \\\"invalid calldata (must have length >= 140)\\\"\\n );\\n\\n // extract bridgeData\\n bridgeData.transactionId = bytes32(bytes8(data[4:12]));\\n bridgeData.receiver = address(bytes20(data[12:32]));\\n bridgeData.destinationChainId = uint64(uint32(bytes4(data[52:56])));\\n\\n // extract acrossData\\n acrossData.refundAddress = address(bytes20(data[32:52])); // depositor\\n acrossData.receivingAssetId = address(bytes20(data[56:76]));\\n acrossData.outputAmount = uint256(bytes32(data[76:108]));\\n acrossData.exclusiveRelayer = address(bytes20(data[108:128]));\\n acrossData.quoteTimestamp = uint32(bytes4(data[128:132]));\\n acrossData.fillDeadline = uint32(bytes4(data[132:136]));\\n acrossData.exclusivityDeadline = uint32(bytes4(data[136:140]));\\n acrossData.message = data[140:];\\n\\n return (bridgeData, acrossData);\\n }\\n\\n /// @notice Decodes calldata that is meant to be used for calling the ERC20 'packed' function\\n /// @param data the calldata to be decoded\\n function decode_startBridgeTokensViaAcrossV3ERC20Packed(\\n bytes calldata data\\n )\\n external\\n pure\\n returns (\\n BridgeData memory bridgeData,\\n AcrossFacetV3.AcrossV3Data memory acrossData\\n )\\n {\\n require(\\n data.length >= 176,\\n \\\"invalid calldata (must have length >= 176)\\\"\\n );\\n\\n bridgeData.transactionId = bytes32(bytes8(data[4:12]));\\n bridgeData.receiver = address(bytes20(data[12:32]));\\n acrossData.refundAddress = address(bytes20(data[32:52])); // depositor\\n bridgeData.sendingAssetId = address(bytes20(data[52:72]));\\n bridgeData.minAmount = uint256(uint128(bytes16(data[72:88])));\\n bridgeData.destinationChainId = uint64(uint32(bytes4(data[88:92])));\\n\\n acrossData.receivingAssetId = address(bytes20(data[92:112]));\\n acrossData.outputAmount = uint256(bytes32(data[112:144]));\\n acrossData.exclusiveRelayer = address(bytes20(data[144:164]));\\n acrossData.quoteTimestamp = uint32(bytes4(data[164:168]));\\n acrossData.fillDeadline = uint32(bytes4(data[168:172]));\\n acrossData.exclusivityDeadline = uint32(bytes4(data[172:176]));\\n acrossData.message = data[176:];\\n\\n return (bridgeData, acrossData);\\n }\\n\\n /// @notice Execute calldata and withdraw asset\\n /// @param _callTo The address to execute the calldata on\\n /// @param _callData The data to execute\\n /// @param _assetAddress Asset to be withdrawn\\n /// @param _to address to withdraw to\\n /// @param _amount amount of asset to withdraw\\n function executeCallAndWithdraw(\\n address _callTo,\\n bytes calldata _callData,\\n address _assetAddress,\\n address _to,\\n uint256 _amount\\n ) external onlyOwner {\\n // execute calldata\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = _callTo.call(_callData);\\n\\n // check success of call\\n if (success) {\\n // call successful - withdraw the asset\\n LibAsset.transferAsset(_assetAddress, payable(_to), _amount);\\n emit CallExecutedAndFundsWithdrawn();\\n } else {\\n // call unsuccessful - revert\\n revert WithdrawFailed();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IAcrossSpokePool.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\ninterface IAcrossSpokePool {\\n function deposit(\\n address recipient, // Recipient address\\n address originToken, // Address of the token\\n uint256 amount, // Token amount\\n uint256 destinationChainId, // ⛓ id\\n int64 relayerFeePct, // see #Fees Calculation\\n uint32 quoteTimestamp, // Timestamp for the quote creation\\n bytes memory message, // Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\\n uint256 maxCount // Used to protect the depositor from frontrunning to guarantee their quote remains valid.\\n ) external payable;\\n\\n function depositV3(\\n address depositor,\\n address recipient,\\n address inputToken,\\n address outputToken,\\n uint256 inputAmount,\\n uint256 outputAmount, // <-- replaces fees\\n uint256 destinationChainId,\\n address exclusiveRelayer,\\n uint32 quoteTimestamp,\\n uint32 fillDeadline,\\n uint32 exclusivityDeadline,\\n bytes calldata message\\n ) external payable;\\n}\\n\"\r\n },\r\n \"src/Helpers/TransferrableOwnership.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { IERC173 } from \\\"../Interfaces/IERC173.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\n\\ncontract TransferrableOwnership is IERC173 {\\n address public owner;\\n address public pendingOwner;\\n\\n /// Errors ///\\n error UnAuthorized();\\n error NoNullOwner();\\n error NewOwnerMustNotBeSelf();\\n error NoPendingOwnershipTransfer();\\n error NotPendingOwner();\\n\\n /// Events ///\\n event OwnershipTransferRequested(\\n address indexed _from,\\n address indexed _to\\n );\\n\\n constructor(address initialOwner) {\\n owner = initialOwner;\\n }\\n\\n modifier onlyOwner() {\\n if (msg.sender != owner) revert UnAuthorized();\\n _;\\n }\\n\\n /// @notice Initiates transfer of ownership to a new address\\n /// @param _newOwner the address to transfer ownership to\\n function transferOwnership(address _newOwner) external onlyOwner {\\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\\n pendingOwner = _newOwner;\\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\\n }\\n\\n /// @notice Cancel transfer of ownership\\n function cancelOwnershipTransfer() external onlyOwner {\\n if (pendingOwner == LibAsset.NULL_ADDRESS)\\n revert NoPendingOwnershipTransfer();\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n\\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\\n function confirmOwnershipTransfer() external {\\n address _pendingOwner = pendingOwner;\\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\\n emit OwnershipTransferred(owner, _pendingOwner);\\n owner = _pendingOwner;\\n pendingOwner = LibAsset.NULL_ADDRESS;\\n }\\n}\\n\"\r\n },\r\n \"src/Facets/AcrossFacetV3.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IAcrossSpokePool } from \\\"../Interfaces/IAcrossSpokePool.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2 } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { InformationMismatch } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title AcrossFacetV3\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Across Protocol\\n/// @custom:version 1.0.0\\ncontract AcrossFacetV3 is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n /// @notice The contract address of the spoke pool on the source chain.\\n IAcrossSpokePool public immutable spokePool;\\n\\n /// @notice The WETH address on the current chain.\\n address public immutable wrappedNative;\\n\\n /// Types ///\\n\\n /// @param receiverAddress The address that will receive the token on dst chain (our Receiver contract or the user-defined receiver address)\\n /// @param refundAddress The address that will be used for potential bridge refunds\\n /// @param receivingAssetId The address of the token to be received at destination chain\\n /// @param outputAmount The amount to be received at destination chain (after fees)\\n /// @param exclusiveRelayer This is the exclusive relayer who can fill the deposit before the exclusivity deadline.\\n /// @param quoteTimestamp The timestamp of the Across quote that was used for this transaction\\n /// @param fillDeadline The destination chain timestamp until which the order can be filled\\n /// @param exclusivityDeadline The timestamp on the destination chain after which any relayer can fill the deposit\\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens\\n struct AcrossV3Data {\\n address receiverAddress;\\n address refundAddress;\\n address receivingAssetId;\\n uint256 outputAmount;\\n address exclusiveRelayer;\\n uint32 quoteTimestamp;\\n uint32 fillDeadline;\\n uint32 exclusivityDeadline;\\n bytes message;\\n }\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _spokePool The contract address of the spoke pool on the source chain.\\n /// @param _wrappedNative The address of the wrapped native token on the source chain.\\n constructor(IAcrossSpokePool _spokePool, address _wrappedNative) {\\n spokePool = _spokePool;\\n wrappedNative = _wrappedNative;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Across\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _acrossData data specific to Across\\n function startBridgeTokensViaAcrossV3(\\n ILiFi.BridgeData memory _bridgeData,\\n AcrossV3Data calldata _acrossData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n validateBridgeData(_bridgeData)\\n doesNotContainSourceSwaps(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData, _acrossData);\\n }\\n\\n /// @notice Performs a swap before bridging via Across\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _acrossData data specific to Across\\n function swapAndStartBridgeTokensViaAcrossV3(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n AcrossV3Data calldata _acrossData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n _startBridge(_bridgeData, _acrossData);\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Across\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _acrossData data specific to Across\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n AcrossV3Data calldata _acrossData\\n ) internal {\\n // validate destination call flag\\n if (_acrossData.message.length > 0 != _bridgeData.hasDestinationCall)\\n revert InformationMismatch();\\n\\n // ensure that receiver addresses match in case of no destination call\\n if (\\n !_bridgeData.hasDestinationCall &&\\n (_bridgeData.receiver != _acrossData.receiverAddress)\\n ) revert InformationMismatch();\\n\\n // check if sendingAsset is native or ERC20\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // NATIVE\\n spokePool.depositV3{ value: _bridgeData.minAmount }(\\n _acrossData.refundAddress, // depositor (also acts as refund address in case release tx cannot be executed)\\n _acrossData.receiverAddress, // recipient (on dst)\\n wrappedNative, // inputToken\\n _acrossData.receivingAssetId, // outputToken\\n _bridgeData.minAmount, // inputAmount\\n _acrossData.outputAmount, // outputAmount\\n _bridgeData.destinationChainId,\\n _acrossData.exclusiveRelayer,\\n _acrossData.quoteTimestamp,\\n _acrossData.fillDeadline,\\n _acrossData.exclusivityDeadline,\\n _acrossData.message\\n );\\n } else {\\n // ERC20\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(spokePool),\\n _bridgeData.minAmount\\n );\\n spokePool.depositV3(\\n _acrossData.refundAddress, // depositor (also acts as refund address in case release tx cannot be executed)\\n _acrossData.receiverAddress, // recipient (on dst)\\n _bridgeData.sendingAssetId, // inputToken\\n _acrossData.receivingAssetId, // outputToken\\n _bridgeData.minAmount, // inputAmount\\n _acrossData.outputAmount, // outputAmount\\n _bridgeData.destinationChainId,\\n _acrossData.exclusiveRelayer,\\n _acrossData.quoteTimestamp,\\n _acrossData.fillDeadline,\\n _acrossData.exclusivityDeadline,\\n _acrossData.message\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"lib/solmate/src/utils/SafeTransferLib.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\nimport {ERC20} from \\\"../tokens/ERC20.sol\\\";\\n\\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\\nlibrary SafeTransferLib {\\n /*//////////////////////////////////////////////////////////////\\n ETH OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferETH(address to, uint256 amount) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Transfer the ETH and store if it succeeded or not.\\n success := call(gas(), to, amount, 0, 0, 0, 0)\\n }\\n\\n require(success, \\\"ETH_TRANSFER_FAILED\\\");\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 OPERATIONS\\n //////////////////////////////////////////////////////////////*/\\n\\n function safeTransferFrom(\\n ERC20 token,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), from) // Append the \\\"from\\\" argument.\\n mstore(add(freeMemoryPointer, 36), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 68), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FROM_FAILED\\\");\\n }\\n\\n function safeTransfer(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"TRANSFER_FAILED\\\");\\n }\\n\\n function safeApprove(\\n ERC20 token,\\n address to,\\n uint256 amount\\n ) internal {\\n bool success;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Get a pointer to some free memory.\\n let freeMemoryPointer := mload(0x40)\\n\\n // Write the abi-encoded calldata into memory, beginning with the function selector.\\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\\n mstore(add(freeMemoryPointer, 4), to) // Append the \\\"to\\\" argument.\\n mstore(add(freeMemoryPointer, 36), amount) // Append the \\\"amount\\\" argument.\\n\\n success := and(\\n // Set success to whether the call reverted, if not we check it either\\n // returned exactly 1 (can't just be non-zero data), or had no return data.\\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\\n // Counterintuitively, this call must be positioned second to the or() call in the\\n // surrounding and() call or else returndatasize() will be zero during the computation.\\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\\n )\\n }\\n\\n require(success, \\\"APPROVE_FAILED\\\");\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IERC173.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\n/// @title ERC-173 Contract Ownership Standard\\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\\n/* is ERC165 */\\ninterface IERC173 {\\n /// @dev This emits when ownership of a contract changes.\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n /// @notice Get the address of the owner\\n /// @return owner_ The address of the owner.\\n function owner() external view returns (address owner_);\\n\\n /// @notice Set the address of the new owner of the contract\\n /// @dev Set _newOwner to address(0) to renounce any ownership.\\n /// @param _newOwner The address of the new owner of the contract\\n function transferOwnership(address _newOwner) external;\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n LibUtil.revertWith(res);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror DiamondIsPaused();\\nerror ExternalCallFailed();\\nerror FunctionDoesNotExist();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/solmate/src/tokens/ERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: AGPL-3.0-only\\npragma solidity >=0.8.0;\\n\\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\\nabstract contract ERC20 {\\n /*//////////////////////////////////////////////////////////////\\n EVENTS\\n //////////////////////////////////////////////////////////////*/\\n\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /*//////////////////////////////////////////////////////////////\\n METADATA STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n string public name;\\n\\n string public symbol;\\n\\n uint8 public immutable decimals;\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 public totalSupply;\\n\\n mapping(address => uint256) public balanceOf;\\n\\n mapping(address => mapping(address => uint256)) public allowance;\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 STORAGE\\n //////////////////////////////////////////////////////////////*/\\n\\n uint256 internal immutable INITIAL_CHAIN_ID;\\n\\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\\n\\n mapping(address => uint256) public nonces;\\n\\n /*//////////////////////////////////////////////////////////////\\n CONSTRUCTOR\\n //////////////////////////////////////////////////////////////*/\\n\\n constructor(\\n string memory _name,\\n string memory _symbol,\\n uint8 _decimals\\n ) {\\n name = _name;\\n symbol = _symbol;\\n decimals = _decimals;\\n\\n INITIAL_CHAIN_ID = block.chainid;\\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n ERC20 LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function approve(address spender, uint256 amount) public virtual returns (bool) {\\n allowance[msg.sender][spender] = amount;\\n\\n emit Approval(msg.sender, spender, amount);\\n\\n return true;\\n }\\n\\n function transfer(address to, uint256 amount) public virtual returns (bool) {\\n balanceOf[msg.sender] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(msg.sender, to, amount);\\n\\n return true;\\n }\\n\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual returns (bool) {\\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\\n\\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\\n\\n balanceOf[from] -= amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n return true;\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n EIP-2612 LOGIC\\n //////////////////////////////////////////////////////////////*/\\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 ) public virtual {\\n require(deadline >= block.timestamp, \\\"PERMIT_DEADLINE_EXPIRED\\\");\\n\\n // Unchecked because the only math done is incrementing\\n // the owner's nonce which cannot realistically overflow.\\n unchecked {\\n address recoveredAddress = ecrecover(\\n keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19\\\\x01\\\",\\n DOMAIN_SEPARATOR(),\\n keccak256(\\n abi.encode(\\n keccak256(\\n \\\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\\\"\\n ),\\n owner,\\n spender,\\n value,\\n nonces[owner]++,\\n deadline\\n )\\n )\\n )\\n ),\\n v,\\n r,\\n s\\n );\\n\\n require(recoveredAddress != address(0) && recoveredAddress == owner, \\\"INVALID_SIGNER\\\");\\n\\n allowance[recoveredAddress][spender] = value;\\n }\\n\\n emit Approval(owner, spender, value);\\n }\\n\\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\\n }\\n\\n function computeDomainSeparator() internal view virtual returns (bytes32) {\\n return\\n keccak256(\\n abi.encode(\\n keccak256(\\\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\\\"),\\n keccak256(bytes(name)),\\n keccak256(\\\"1\\\"),\\n block.chainid,\\n address(this)\\n )\\n );\\n }\\n\\n /*//////////////////////////////////////////////////////////////\\n INTERNAL MINT/BURN LOGIC\\n //////////////////////////////////////////////////////////////*/\\n\\n function _mint(address to, uint256 amount) internal virtual {\\n totalSupply += amount;\\n\\n // Cannot overflow because the sum of all user\\n // balances can't exceed the max uint256 value.\\n unchecked {\\n balanceOf[to] += amount;\\n }\\n\\n emit Transfer(address(0), to, amount);\\n }\\n\\n function _burn(address from, uint256 amount) internal virtual {\\n balanceOf[from] -= amount;\\n\\n // Cannot underflow because a user's balance\\n // will never be larger than the total supply.\\n unchecked {\\n totalSupply -= amount;\\n }\\n\\n emit Transfer(from, address(0), amount);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n\\n function revertWith(bytes memory data) internal pure {\\n assembly {\\n let dataSize := mload(data) // Load the size of the data\\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\\n revert(dataPtr, dataSize) // Revert with the given data\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"solady/=lib/solady/src/\",\r\n \"permit2/=lib/Permit2/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"Permit2/=lib/Permit2/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"forge-gas-snapshot/=lib/Permit2/lib/forge-gas-snapshot/src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IAcrossSpokePool\",\"name\":\"_spokePool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_wrappedNative\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NewOwnerMustNotBeSelf\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoNullOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoPendingOwnershipTransfer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotPendingOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnAuthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WithdrawFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CallExecutedAndFundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes8\",\"name\":\"_transactionId\",\"type\":\"bytes8\"}],\"name\":\"LiFiAcrossTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"cancelOwnershipTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"confirmOwnershipTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"decode_startBridgeTokensViaAcrossV3ERC20Packed\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"receiverAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"refundAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"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\"}],\"internalType\":\"struct AcrossFacetV3.AcrossV3Data\",\"name\":\"acrossData\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"decode_startBridgeTokensViaAcrossV3NativePacked\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"receiverAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"refundAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"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\"}],\"internalType\":\"struct AcrossFacetV3.AcrossV3Data\",\"name\":\"acrossData\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destinationChainId\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"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\"}],\"internalType\":\"struct AcrossFacetPackedV3.PackedParameters\",\"name\":\"_parameters\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"inputAmount\",\"type\":\"uint256\"}],\"name\":\"encode_startBridgeTokensViaAcrossV3ERC20Packed\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destinationChainId\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"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\"}],\"internalType\":\"struct AcrossFacetPackedV3.PackedParameters\",\"name\":\"_parameters\",\"type\":\"tuple\"}],\"name\":\"encode_startBridgeTokensViaAcrossV3NativePacked\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_callTo\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_callData\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"_assetAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"executeCallAndWithdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokensToApprove\",\"type\":\"address[]\"}],\"name\":\"setApprovalForBridge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"spokePool\",\"outputs\":[{\"internalType\":\"contract IAcrossSpokePool\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destinationChainId\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"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\"}],\"internalType\":\"struct AcrossFacetPackedV3.PackedParameters\",\"name\":\"_parameters\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"inputAmount\",\"type\":\"uint256\"}],\"name\":\"startBridgeTokensViaAcrossV3ERC20Min\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBridgeTokensViaAcrossV3ERC20Packed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"depositor\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destinationChainId\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"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\"}],\"internalType\":\"struct AcrossFacetPackedV3.PackedParameters\",\"name\":\"_parameters\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaAcrossV3NativeMin\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startBridgeTokensViaAcrossV3NativePacked\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"wrappedNative\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + ContractName: "AcrossFacetPackedV3", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000005c7bcd6e7de5423a257d81b442095a1a6ced35c5000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000011f1022ca6adef6400e5677528a80d49a069c00c", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/AcrossFacetPackedV3.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport { IAcrossSpokePool } from \"../Interfaces/IAcrossSpokePool.sol\";\nimport { TransferrableOwnership } from \"../Helpers/TransferrableOwnership.sol\";\nimport { AcrossFacetV3 } from \"./AcrossFacetV3.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { ERC20, SafeTransferLib } from \"solmate/utils/SafeTransferLib.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\n\n/// @title AcrossFacetPackedV3\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Across in a gas-optimized way\n/// @custom:version 1.2.0\ncontract AcrossFacetPackedV3 is ILiFi, TransferrableOwnership {\n using SafeTransferLib for ERC20;\n\n /// Storage ///\n\n /// @notice The contract address of the cbridge on the source chain.\n IAcrossSpokePool public immutable spokePool;\n\n /// @notice The WETH address on the current chain.\n address public immutable wrappedNative;\n\n /// Events ///\n\n event LiFiAcrossTransfer(bytes8 _transactionId);\n event CallExecutedAndFundsWithdrawn();\n\n /// Errors ///\n\n error WithdrawFailed();\n\n // using this struct to bundle parameters is required since otherwise we run into stack-too-deep errors\n // (Solidity can only handle a limited amount of parameters at any given time)\n struct PackedParameters {\n bytes32 transactionId;\n address receiver;\n address depositor;\n uint64 destinationChainId;\n address receivingAssetId;\n uint256 outputAmount;\n address exclusiveRelayer;\n uint32 quoteTimestamp;\n uint32 fillDeadline;\n uint32 exclusivityDeadline;\n bytes message;\n }\n\n /// Constructor ///\n\n /// @notice Initialize the contract\n /// @param _spokePool The contract address of the spoke pool on the source chain\n /// @param _wrappedNative The address of the wrapped native token on the source chain\n /// @param _owner The address of the contract owner\n constructor(\n IAcrossSpokePool _spokePool,\n address _wrappedNative,\n address _owner\n ) TransferrableOwnership(_owner) {\n spokePool = _spokePool;\n wrappedNative = _wrappedNative;\n }\n\n /// External Methods ///\n\n /// @dev Only meant to be called outside of the context of the diamond\n /// @notice Sets approval for the Across spoke pool Router to spend the specified token\n /// @param tokensToApprove The tokens to approve to the Across spoke pool\n function setApprovalForBridge(\n address[] calldata tokensToApprove\n ) external onlyOwner {\n for (uint256 i; i < tokensToApprove.length; i++) {\n // Give Across spoke pool approval to pull tokens from this facet\n LibAsset.maxApproveERC20(\n IERC20(tokensToApprove[i]),\n address(spokePool),\n type(uint256).max\n );\n }\n }\n\n /// @notice Bridges native tokens via Across (packed implementation)\n /// @dev Calldata mapping:\n /// [0:4] - function selector\n /// [4:12] - transactionId\n /// [12:32] - receiver\n /// [32:52] - depositor\n /// [52:56] - destinationChainId\n /// [56:76] - receivingAssetId\n /// [76:108] - outputAmount\n /// [108:128] - exclusiveRelayer\n /// [128:132] - quoteTimestamp\n /// [132:136] - fillDeadline\n /// [136:140] - exclusivityDeadline\n /// [140:] - message\n function startBridgeTokensViaAcrossV3NativePacked() external payable {\n // call Across spoke pool to bridge assets\n spokePool.depositV3{ value: msg.value }(\n address(bytes20(msg.data[32:52])), // depositor\n address(bytes20(msg.data[12:32])), // recipient\n wrappedNative, // inputToken\n address(bytes20(msg.data[56:76])), // outputToken\n msg.value, // inputAmount\n uint256(bytes32(msg.data[76:108])), // outputAmount\n uint64(uint32(bytes4(msg.data[52:56]))), // destinationChainId\n address(bytes20(msg.data[108:128])), // exclusiveRelayer\n uint32(bytes4(msg.data[128:132])), // quoteTimestamp\n uint32(bytes4(msg.data[132:136])), // fillDeadline\n uint32(bytes4(msg.data[136:140])), // exclusivityDeadline\n msg.data[140:msg.data.length]\n );\n\n emit LiFiAcrossTransfer(bytes8(msg.data[4:12]));\n }\n\n /// @notice Bridges native tokens via Across (minimal implementation)\n /// @param _parameters Contains all parameters required for native bridging with AcrossV3\n function startBridgeTokensViaAcrossV3NativeMin(\n PackedParameters calldata _parameters\n ) external payable {\n // call Across spoke pool to bridge assets\n spokePool.depositV3{ value: msg.value }(\n _parameters.depositor, // depositor\n _parameters.receiver,\n wrappedNative, // inputToken\n _parameters.receivingAssetId, // outputToken\n msg.value, // inputAmount\n _parameters.outputAmount,\n _parameters.destinationChainId,\n _parameters.exclusiveRelayer,\n _parameters.quoteTimestamp,\n _parameters.fillDeadline,\n _parameters.exclusivityDeadline,\n _parameters.message\n );\n\n emit LiFiAcrossTransfer(bytes8(_parameters.transactionId));\n }\n\n /// @notice Bridges ERC20 tokens via Across (packed implementation)\n /// @dev Calldata mapping:\n /// [0:4] - function selector\n /// [4:12] - transactionId\n /// [12:32] - receiver\n /// [32:52] - depositor\n /// [52:72] - sendingAssetId\n /// [72:88] - inputAmount\n /// [88:92] - destinationChainId\n /// [92:112] - receivingAssetId\n /// [112:144] - outputAmount\n /// [144:164] - exclusiveRelayer\n /// [164:168] - quoteTimestamp\n /// [168:172] - fillDeadline\n /// [172:176] - exclusivityDeadline\n /// [176:] - message\n function startBridgeTokensViaAcrossV3ERC20Packed() external {\n address sendingAssetId = address(bytes20(msg.data[52:72]));\n uint256 inputAmount = uint256(uint128(bytes16(msg.data[72:88])));\n\n ERC20(sendingAssetId).safeTransferFrom(\n msg.sender,\n address(this),\n inputAmount\n );\n\n spokePool.depositV3(\n address(bytes20(msg.data[32:52])), // depositor\n address(bytes20(msg.data[12:32])), // recipient\n sendingAssetId, // inputToken\n address(bytes20(msg.data[92:112])), // outputToken\n inputAmount, // inputAmount\n uint256(bytes32(msg.data[112:144])), // outputAmount\n uint64(uint32(bytes4(msg.data[88:92]))), // destinationChainId\n address(bytes20(msg.data[144:164])), // exclusiveRelayer\n uint32(bytes4(msg.data[164:168])), // quoteTimestamp\n uint32(bytes4(msg.data[168:172])), // fillDeadline\n uint32(bytes4(msg.data[172:176])), // exclusivityDeadline\n msg.data[176:msg.data.length]\n );\n\n emit LiFiAcrossTransfer(bytes8(msg.data[4:12]));\n }\n\n /// @notice Bridges ERC20 tokens via Across (minimal implementation)\n /// @param _parameters Contains all base parameters required for bridging with AcrossV3\n /// @param sendingAssetId The address of the asset/token to be bridged\n /// @param inputAmount The amount to be bridged (including fees)\n function startBridgeTokensViaAcrossV3ERC20Min(\n PackedParameters calldata _parameters,\n address sendingAssetId,\n uint256 inputAmount\n ) external {\n // Deposit assets\n ERC20(sendingAssetId).safeTransferFrom(\n msg.sender,\n address(this),\n inputAmount\n );\n\n // call Across SpokePool\n spokePool.depositV3(\n _parameters.depositor, // depositor\n _parameters.receiver,\n sendingAssetId, // inputToken\n _parameters.receivingAssetId, // outputToken\n inputAmount,\n _parameters.outputAmount,\n _parameters.destinationChainId,\n _parameters.exclusiveRelayer,\n _parameters.quoteTimestamp,\n _parameters.fillDeadline,\n _parameters.exclusivityDeadline,\n _parameters.message\n );\n\n emit LiFiAcrossTransfer(bytes8(_parameters.transactionId));\n }\n\n /// @notice Encodes calldata that can be used to call the native 'packed' function\n /// @param _parameters Contains all parameters required for native bridging with AcrossV3\n function encode_startBridgeTokensViaAcrossV3NativePacked(\n PackedParameters calldata _parameters\n ) external pure returns (bytes memory) {\n // there are already existing networks with chainIds outside uint32 range but since we not support either of them yet,\n // we feel comfortable using this approach to save further gas\n require(\n _parameters.destinationChainId <= type(uint32).max,\n \"destinationChainId value passed too big to fit in uint32\"\n );\n\n return\n bytes.concat(\n AcrossFacetPackedV3\n .startBridgeTokensViaAcrossV3NativePacked\n .selector,\n bytes8(_parameters.transactionId),\n bytes20(_parameters.receiver),\n bytes20(_parameters.depositor),\n bytes4(uint32(_parameters.destinationChainId)),\n bytes20(_parameters.receivingAssetId),\n bytes32(_parameters.outputAmount),\n bytes20(_parameters.exclusiveRelayer),\n bytes4(_parameters.quoteTimestamp),\n bytes4(_parameters.fillDeadline),\n bytes4(_parameters.exclusivityDeadline),\n _parameters.message\n );\n }\n\n /// @notice Encodes calldata that can be used to call the ERC20 'packed' function\n /// @param _parameters Contains all base parameters required for bridging with AcrossV3\n /// @param sendingAssetId The address of the asset/token to be bridged\n /// @param inputAmount The amount to be bridged (including fees)\n function encode_startBridgeTokensViaAcrossV3ERC20Packed(\n PackedParameters calldata _parameters,\n address sendingAssetId,\n uint256 inputAmount\n ) external pure returns (bytes memory) {\n // there are already existing networks with chainIds outside uint32 range but since we not support either of them yet,\n // we feel comfortable using this approach to save further gas\n require(\n _parameters.destinationChainId <= type(uint32).max,\n \"destinationChainId value passed too big to fit in uint32\"\n );\n\n require(\n inputAmount <= type(uint128).max,\n \"inputAmount value passed too big to fit in uint128\"\n );\n\n // Split the concatenation into parts to avoid \"stack too deep\" errors\n bytes memory part1 = bytes.concat(\n AcrossFacetPackedV3\n .startBridgeTokensViaAcrossV3ERC20Packed\n .selector,\n bytes8(_parameters.transactionId),\n bytes20(_parameters.receiver),\n bytes20(_parameters.depositor),\n bytes20(sendingAssetId)\n );\n\n bytes memory part2 = bytes.concat(\n bytes16(uint128(inputAmount)),\n bytes4(uint32(_parameters.destinationChainId)),\n bytes20(_parameters.receivingAssetId),\n bytes32(_parameters.outputAmount)\n );\n\n bytes memory part3 = bytes.concat(\n bytes20(_parameters.exclusiveRelayer),\n bytes4(_parameters.quoteTimestamp),\n bytes4(_parameters.fillDeadline),\n bytes4(_parameters.exclusivityDeadline)\n );\n\n // Combine all parts with the message\n return bytes.concat(part1, part2, part3, _parameters.message);\n }\n\n /// @notice Decodes calldata that is meant to be used for calling the native 'packed' function\n /// @param data the calldata to be decoded\n function decode_startBridgeTokensViaAcrossV3NativePacked(\n bytes calldata data\n )\n external\n pure\n returns (\n BridgeData memory bridgeData,\n AcrossFacetV3.AcrossV3Data memory acrossData\n )\n {\n require(\n data.length >= 140,\n \"invalid calldata (must have length >= 140)\"\n );\n\n // extract bridgeData\n bridgeData.transactionId = bytes32(bytes8(data[4:12]));\n bridgeData.receiver = address(bytes20(data[12:32]));\n bridgeData.destinationChainId = uint64(uint32(bytes4(data[52:56])));\n\n // extract acrossData\n acrossData.refundAddress = address(bytes20(data[32:52])); // depositor\n acrossData.receivingAssetId = address(bytes20(data[56:76]));\n acrossData.outputAmount = uint256(bytes32(data[76:108]));\n acrossData.exclusiveRelayer = address(bytes20(data[108:128]));\n acrossData.quoteTimestamp = uint32(bytes4(data[128:132]));\n acrossData.fillDeadline = uint32(bytes4(data[132:136]));\n acrossData.exclusivityDeadline = uint32(bytes4(data[136:140]));\n acrossData.message = data[140:];\n\n return (bridgeData, acrossData);\n }\n\n /// @notice Decodes calldata that is meant to be used for calling the ERC20 'packed' function\n /// @param data the calldata to be decoded\n function decode_startBridgeTokensViaAcrossV3ERC20Packed(\n bytes calldata data\n )\n external\n pure\n returns (\n BridgeData memory bridgeData,\n AcrossFacetV3.AcrossV3Data memory acrossData\n )\n {\n require(\n data.length >= 176,\n \"invalid calldata (must have length >= 176)\"\n );\n\n bridgeData.transactionId = bytes32(bytes8(data[4:12]));\n bridgeData.receiver = address(bytes20(data[12:32]));\n acrossData.refundAddress = address(bytes20(data[32:52])); // depositor\n bridgeData.sendingAssetId = address(bytes20(data[52:72]));\n bridgeData.minAmount = uint256(uint128(bytes16(data[72:88])));\n bridgeData.destinationChainId = uint64(uint32(bytes4(data[88:92])));\n\n acrossData.receivingAssetId = address(bytes20(data[92:112]));\n acrossData.outputAmount = uint256(bytes32(data[112:144]));\n acrossData.exclusiveRelayer = address(bytes20(data[144:164]));\n acrossData.quoteTimestamp = uint32(bytes4(data[164:168]));\n acrossData.fillDeadline = uint32(bytes4(data[168:172]));\n acrossData.exclusivityDeadline = uint32(bytes4(data[172:176]));\n acrossData.message = data[176:];\n\n return (bridgeData, acrossData);\n }\n\n /// @notice Execute calldata and withdraw asset\n /// @param _callTo The address to execute the calldata on\n /// @param _callData The data to execute\n /// @param _assetAddress Asset to be withdrawn\n /// @param _to address to withdraw to\n /// @param _amount amount of asset to withdraw\n function executeCallAndWithdraw(\n address _callTo,\n bytes calldata _callData,\n address _assetAddress,\n address _to,\n uint256 _amount\n ) external onlyOwner {\n // execute calldata\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = _callTo.call(_callData);\n\n // check success of call\n if (success) {\n // call successful - withdraw the asset\n LibAsset.transferAsset(_assetAddress, payable(_to), _amount);\n emit CallExecutedAndFundsWithdrawn();\n } else {\n // call unsuccessful - revert\n revert WithdrawFailed();\n }\n }\n}\n" + }, + "src/Interfaces/IAcrossSpokePool.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\ninterface IAcrossSpokePool {\n function deposit(\n address recipient, // Recipient address\n address originToken, // Address of the token\n uint256 amount, // Token amount\n uint256 destinationChainId, // ⛓ id\n int64 relayerFeePct, // see #Fees Calculation\n uint32 quoteTimestamp, // Timestamp for the quote creation\n bytes memory message, // Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\n uint256 maxCount // Used to protect the depositor from frontrunning to guarantee their quote remains valid.\n ) external payable;\n\n function depositV3(\n address depositor,\n address recipient,\n address inputToken,\n address outputToken,\n uint256 inputAmount,\n uint256 outputAmount, // <-- replaces fees\n uint256 destinationChainId,\n address exclusiveRelayer,\n uint32 quoteTimestamp,\n uint32 fillDeadline,\n uint32 exclusivityDeadline,\n bytes calldata message\n ) external payable;\n}\n" + }, + "src/Helpers/TransferrableOwnership.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { IERC173 } from \"../Interfaces/IERC173.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\n\ncontract TransferrableOwnership is IERC173 {\n address public owner;\n address public pendingOwner;\n\n /// Errors ///\n error UnAuthorized();\n error NoNullOwner();\n error NewOwnerMustNotBeSelf();\n error NoPendingOwnershipTransfer();\n error NotPendingOwner();\n\n /// Events ///\n event OwnershipTransferRequested(\n address indexed _from,\n address indexed _to\n );\n\n constructor(address initialOwner) {\n owner = initialOwner;\n }\n\n modifier onlyOwner() {\n if (msg.sender != owner) revert UnAuthorized();\n _;\n }\n\n /// @notice Initiates transfer of ownership to a new address\n /// @param _newOwner the address to transfer ownership to\n function transferOwnership(address _newOwner) external onlyOwner {\n if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();\n if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();\n pendingOwner = _newOwner;\n emit OwnershipTransferRequested(msg.sender, pendingOwner);\n }\n\n /// @notice Cancel transfer of ownership\n function cancelOwnershipTransfer() external onlyOwner {\n if (pendingOwner == LibAsset.NULL_ADDRESS)\n revert NoPendingOwnershipTransfer();\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n\n /// @notice Confirms transfer of ownership to the calling address (msg.sender)\n function confirmOwnershipTransfer() external {\n address _pendingOwner = pendingOwner;\n if (msg.sender != _pendingOwner) revert NotPendingOwner();\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = LibAsset.NULL_ADDRESS;\n }\n}\n" + }, + "src/Facets/AcrossFacetV3.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IAcrossSpokePool } from \"../Interfaces/IAcrossSpokePool.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2 } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { InformationMismatch } from \"../Errors/GenericErrors.sol\";\n\n/// @title AcrossFacetV3\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Across Protocol\n/// @custom:version 1.0.0\ncontract AcrossFacetV3 is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n /// @notice The contract address of the spoke pool on the source chain.\n IAcrossSpokePool public immutable spokePool;\n\n /// @notice The WETH address on the current chain.\n address public immutable wrappedNative;\n\n /// Types ///\n\n /// @param receiverAddress The address that will receive the token on dst chain (our Receiver contract or the user-defined receiver address)\n /// @param refundAddress The address that will be used for potential bridge refunds\n /// @param receivingAssetId The address of the token to be received at destination chain\n /// @param outputAmount The amount to be received at destination chain (after fees)\n /// @param exclusiveRelayer This is the exclusive relayer who can fill the deposit before the exclusivity deadline.\n /// @param quoteTimestamp The timestamp of the Across quote that was used for this transaction\n /// @param fillDeadline The destination chain timestamp until which the order can be filled\n /// @param exclusivityDeadline The timestamp on the destination chain after which any relayer can fill the deposit\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens\n struct AcrossV3Data {\n address receiverAddress;\n address refundAddress;\n address receivingAssetId;\n uint256 outputAmount;\n address exclusiveRelayer;\n uint32 quoteTimestamp;\n uint32 fillDeadline;\n uint32 exclusivityDeadline;\n bytes message;\n }\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _spokePool The contract address of the spoke pool on the source chain.\n /// @param _wrappedNative The address of the wrapped native token on the source chain.\n constructor(IAcrossSpokePool _spokePool, address _wrappedNative) {\n spokePool = _spokePool;\n wrappedNative = _wrappedNative;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Across\n /// @param _bridgeData the core information needed for bridging\n /// @param _acrossData data specific to Across\n function startBridgeTokensViaAcrossV3(\n ILiFi.BridgeData memory _bridgeData,\n AcrossV3Data calldata _acrossData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n validateBridgeData(_bridgeData)\n doesNotContainSourceSwaps(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData, _acrossData);\n }\n\n /// @notice Performs a swap before bridging via Across\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _acrossData data specific to Across\n function swapAndStartBridgeTokensViaAcrossV3(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n AcrossV3Data calldata _acrossData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n _startBridge(_bridgeData, _acrossData);\n }\n\n /// Internal Methods ///\n\n /// @dev Contains the business logic for the bridge via Across\n /// @param _bridgeData the core information needed for bridging\n /// @param _acrossData data specific to Across\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n AcrossV3Data calldata _acrossData\n ) internal {\n // validate destination call flag\n if (_acrossData.message.length > 0 != _bridgeData.hasDestinationCall)\n revert InformationMismatch();\n\n // ensure that receiver addresses match in case of no destination call\n if (\n !_bridgeData.hasDestinationCall &&\n (_bridgeData.receiver != _acrossData.receiverAddress)\n ) revert InformationMismatch();\n\n // check if sendingAsset is native or ERC20\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // NATIVE\n spokePool.depositV3{ value: _bridgeData.minAmount }(\n _acrossData.refundAddress, // depositor (also acts as refund address in case release tx cannot be executed)\n _acrossData.receiverAddress, // recipient (on dst)\n wrappedNative, // inputToken\n _acrossData.receivingAssetId, // outputToken\n _bridgeData.minAmount, // inputAmount\n _acrossData.outputAmount, // outputAmount\n _bridgeData.destinationChainId,\n _acrossData.exclusiveRelayer,\n _acrossData.quoteTimestamp,\n _acrossData.fillDeadline,\n _acrossData.exclusivityDeadline,\n _acrossData.message\n );\n } else {\n // ERC20\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(spokePool),\n _bridgeData.minAmount\n );\n spokePool.depositV3(\n _acrossData.refundAddress, // depositor (also acts as refund address in case release tx cannot be executed)\n _acrossData.receiverAddress, // recipient (on dst)\n _bridgeData.sendingAssetId, // inputToken\n _acrossData.receivingAssetId, // outputToken\n _bridgeData.minAmount, // inputAmount\n _acrossData.outputAmount, // outputAmount\n _bridgeData.destinationChainId,\n _acrossData.exclusiveRelayer,\n _acrossData.quoteTimestamp,\n _acrossData.fillDeadline,\n _acrossData.exclusivityDeadline,\n _acrossData.message\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "lib/solmate/src/utils/SafeTransferLib.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20} from \"../tokens/ERC20.sol\";\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.\n/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n /*//////////////////////////////////////////////////////////////\n ETH OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferETH(address to, uint256 amount) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Transfer the ETH and store if it succeeded or not.\n success := call(gas(), to, amount, 0, 0, 0, 0)\n }\n\n require(success, \"ETH_TRANSFER_FAILED\");\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 OPERATIONS\n //////////////////////////////////////////////////////////////*/\n\n function safeTransferFrom(\n ERC20 token,\n address from,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), from) // Append the \"from\" argument.\n mstore(add(freeMemoryPointer, 36), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 68), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FROM_FAILED\");\n }\n\n function safeTransfer(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"TRANSFER_FAILED\");\n }\n\n function safeApprove(\n ERC20 token,\n address to,\n uint256 amount\n ) internal {\n bool success;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Get a pointer to some free memory.\n let freeMemoryPointer := mload(0x40)\n\n // Write the abi-encoded calldata into memory, beginning with the function selector.\n mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\n mstore(add(freeMemoryPointer, 4), to) // Append the \"to\" argument.\n mstore(add(freeMemoryPointer, 36), amount) // Append the \"amount\" argument.\n\n success := and(\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),\n // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.\n // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.\n // Counterintuitively, this call must be positioned second to the or() call in the\n // surrounding and() call or else returndatasize() will be zero during the computation.\n call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)\n )\n }\n\n require(success, \"APPROVE_FAILED\");\n }\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Interfaces/IERC173.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\n/// @title ERC-173 Contract Ownership Standard\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\n/* is ERC165 */\ninterface IERC173 {\n /// @dev This emits when ownership of a contract changes.\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n /// @notice Get the address of the owner\n /// @return owner_ The address of the owner.\n function owner() external view returns (address owner_);\n\n /// @notice Set the address of the new owner of the contract\n /// @dev Set _newOwner to address(0) to renounce any ownership.\n /// @param _newOwner The address of the new owner of the contract\n function transferOwnership(address _newOwner) external;\n}\n" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n LibUtil.revertWith(res);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror DiamondIsPaused();\nerror ExternalCallFailed();\nerror FunctionDoesNotExist();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/solmate/src/tokens/ERC20.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n /*//////////////////////////////////////////////////////////////\n EVENTS\n //////////////////////////////////////////////////////////////*/\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /*//////////////////////////////////////////////////////////////\n METADATA STORAGE\n //////////////////////////////////////////////////////////////*/\n\n string public name;\n\n string public symbol;\n\n uint8 public immutable decimals;\n\n /*//////////////////////////////////////////////////////////////\n ERC20 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 public totalSupply;\n\n mapping(address => uint256) public balanceOf;\n\n mapping(address => mapping(address => uint256)) public allowance;\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 STORAGE\n //////////////////////////////////////////////////////////////*/\n\n uint256 internal immutable INITIAL_CHAIN_ID;\n\n bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;\n\n mapping(address => uint256) public nonces;\n\n /*//////////////////////////////////////////////////////////////\n CONSTRUCTOR\n //////////////////////////////////////////////////////////////*/\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) {\n name = _name;\n symbol = _symbol;\n decimals = _decimals;\n\n INITIAL_CHAIN_ID = block.chainid;\n INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();\n }\n\n /*//////////////////////////////////////////////////////////////\n ERC20 LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function approve(address spender, uint256 amount) public virtual returns (bool) {\n allowance[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n\n return true;\n }\n\n function transfer(address to, uint256 amount) public virtual returns (bool) {\n balanceOf[msg.sender] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(msg.sender, to, amount);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual returns (bool) {\n uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n balanceOf[from] -= amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n return true;\n }\n\n /*//////////////////////////////////////////////////////////////\n EIP-2612 LOGIC\n //////////////////////////////////////////////////////////////*/\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 ) public virtual {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n // Unchecked because the only math done is incrementing\n // the owner's nonce which cannot realistically overflow.\n unchecked {\n address recoveredAddress = ecrecover(\n keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(\n abi.encode(\n keccak256(\n \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n ),\n owner,\n spender,\n value,\n nonces[owner]++,\n deadline\n )\n )\n )\n ),\n v,\n r,\n s\n );\n\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n allowance[recoveredAddress][spender] = value;\n }\n\n emit Approval(owner, spender, value);\n }\n\n function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();\n }\n\n function computeDomainSeparator() internal view virtual returns (bytes32) {\n return\n keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(\"1\"),\n block.chainid,\n address(this)\n )\n );\n }\n\n /*//////////////////////////////////////////////////////////////\n INTERNAL MINT/BURN LOGIC\n //////////////////////////////////////////////////////////////*/\n\n function _mint(address to, uint256 amount) internal virtual {\n totalSupply += amount;\n\n // Cannot overflow because the sum of all user\n // balances can't exceed the max uint256 value.\n unchecked {\n balanceOf[to] += amount;\n }\n\n emit Transfer(address(0), to, amount);\n }\n\n function _burn(address from, uint256 amount) internal virtual {\n balanceOf[from] -= amount;\n\n // Cannot underflow because a user's balance\n // will never be larger than the total supply.\n unchecked {\n totalSupply -= amount;\n }\n\n emit Transfer(from, address(0), amount);\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n\n function revertWith(bytes memory data) internal pure {\n assembly {\n let dataSize := mload(data) // Load the size of the data\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\n revert(dataPtr, dataSize) // Revert with the given data\n }\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "solady/=lib/solady/src/", + "permit2/=lib/Permit2/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "Permit2/=lib/Permit2/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "forge-gas-snapshot/=lib/Permit2/lib/forge-gas-snapshot/src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +1.2.0 + Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... /AcrossFacetV3 +0x5052fc5c7486162dedf7458e1f7c6abafbcd6895 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/AcrossFacetV3.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IAcrossSpokePool } from \\\"../Interfaces/IAcrossSpokePool.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2 } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { InformationMismatch } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title AcrossFacetV3\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through Across Protocol\\n/// @custom:version 1.1.0\\ncontract AcrossFacetV3 is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n /// @notice The contract address of the spoke pool on the source chain.\\n IAcrossSpokePool public immutable spokePool;\\n\\n /// @notice The WETH address on the current chain.\\n address public immutable wrappedNative;\\n\\n /// Types ///\\n\\n /// @param receiverAddress The address that will receive the token on dst chain (our Receiver contract or the user-defined receiver address)\\n /// @param refundAddress The address that will be used for potential bridge refunds\\n /// @param receivingAssetId The address of the token to be received at destination chain\\n /// @param outputAmount The amount to be received at destination chain (after fees)\\n /// @param outputAmountPercent The percentage of the output amount with 18 decimal precision (0.7550e18 = 75.50%, 0.99e18 = 99.00%)\\n /// @param exclusiveRelayer This is the exclusive relayer who can fill the deposit before the exclusivity deadline.\\n /// @param quoteTimestamp The timestamp of the Across quote that was used for this transaction\\n /// @param fillDeadline The destination chain timestamp until which the order can be filled\\n /// @param exclusivityDeadline The timestamp on the destination chain after which any relayer can fill the deposit\\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens\\n struct AcrossV3Data {\\n address receiverAddress;\\n address refundAddress;\\n address receivingAssetId;\\n uint256 outputAmount;\\n uint64 outputAmountPercent;\\n address exclusiveRelayer;\\n uint32 quoteTimestamp;\\n uint32 fillDeadline;\\n uint32 exclusivityDeadline;\\n bytes message;\\n }\\n\\n /// Constructor ///\\n\\n /// @notice Initialize the contract.\\n /// @param _spokePool The contract address of the spoke pool on the source chain.\\n /// @param _wrappedNative The address of the wrapped native token on the source chain.\\n constructor(IAcrossSpokePool _spokePool, address _wrappedNative) {\\n spokePool = _spokePool;\\n wrappedNative = _wrappedNative;\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via Across\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _acrossData data specific to Across\\n function startBridgeTokensViaAcrossV3(\\n ILiFi.BridgeData memory _bridgeData,\\n AcrossV3Data calldata _acrossData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n validateBridgeData(_bridgeData)\\n doesNotContainSourceSwaps(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(_bridgeData, _acrossData);\\n }\\n\\n /// @notice Performs a swap before bridging via Across\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _swapData an array of swap related data for performing swaps before bridging\\n /// @param _acrossData data specific to Across\\n function swapAndStartBridgeTokensViaAcrossV3(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n AcrossV3Data calldata _acrossData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n validateBridgeData(_bridgeData)\\n {\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n\\n // Create modified across data with calculated output amount\\n AcrossV3Data memory modifiedAcrossData = _acrossData;\\n modifiedAcrossData.outputAmount =\\n (_bridgeData.minAmount * _acrossData.outputAmountPercent) /\\n 1e18;\\n\\n _startBridge(_bridgeData, modifiedAcrossData);\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Contains the business logic for the bridge via Across\\n /// @param _bridgeData the core information needed for bridging\\n /// @param _acrossData data specific to Across\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n AcrossV3Data memory _acrossData\\n ) internal {\\n // validate destination call flag\\n if (_acrossData.message.length > 0 != _bridgeData.hasDestinationCall)\\n revert InformationMismatch();\\n\\n // ensure that receiver addresses match in case of no destination call\\n if (\\n !_bridgeData.hasDestinationCall &&\\n (_bridgeData.receiver != _acrossData.receiverAddress)\\n ) revert InformationMismatch();\\n\\n // check if sendingAsset is native or ERC20\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // NATIVE\\n spokePool.depositV3{ value: _bridgeData.minAmount }(\\n _acrossData.refundAddress, // depositor (also acts as refund address in case release tx cannot be executed)\\n _acrossData.receiverAddress, // recipient (on dst)\\n wrappedNative, // inputToken\\n _acrossData.receivingAssetId, // outputToken\\n _bridgeData.minAmount, // inputAmount\\n _acrossData.outputAmount, // outputAmount\\n _bridgeData.destinationChainId,\\n _acrossData.exclusiveRelayer,\\n _acrossData.quoteTimestamp,\\n _acrossData.fillDeadline,\\n _acrossData.exclusivityDeadline,\\n _acrossData.message\\n );\\n } else {\\n // ERC20\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(spokePool),\\n _bridgeData.minAmount\\n );\\n spokePool.depositV3(\\n _acrossData.refundAddress, // depositor (also acts as refund address in case release tx cannot be executed)\\n _acrossData.receiverAddress, // recipient (on dst)\\n _bridgeData.sendingAssetId, // inputToken\\n _acrossData.receivingAssetId, // outputToken\\n _bridgeData.minAmount, // inputAmount\\n _acrossData.outputAmount, // outputAmount\\n _bridgeData.destinationChainId,\\n _acrossData.exclusiveRelayer,\\n _acrossData.quoteTimestamp,\\n _acrossData.fillDeadline,\\n _acrossData.exclusivityDeadline,\\n _acrossData.message\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IAcrossSpokePool.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\ninterface IAcrossSpokePool {\\n function deposit(\\n address recipient, // Recipient address\\n address originToken, // Address of the token\\n uint256 amount, // Token amount\\n uint256 destinationChainId, // ⛓ id\\n int64 relayerFeePct, // see #Fees Calculation\\n uint32 quoteTimestamp, // Timestamp for the quote creation\\n bytes memory message, // Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\\n uint256 maxCount // Used to protect the depositor from frontrunning to guarantee their quote remains valid.\\n ) external payable;\\n\\n function depositV3(\\n address depositor,\\n address recipient,\\n address inputToken,\\n address outputToken,\\n uint256 inputAmount,\\n uint256 outputAmount, // <-- replaces fees\\n uint256 destinationChainId,\\n address exclusiveRelayer,\\n uint32 quoteTimestamp,\\n uint32 fillDeadline,\\n uint32 exclusivityDeadline,\\n bytes calldata message\\n ) external payable;\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity ^0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @custom:version 1.0.1\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n address internal constant NON_EVM_ADDRESS =\\n 0x11f111f111f111F111f111f111F111f111f111F1;\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n LibUtil.revertWith(res);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror DiamondIsPaused();\\nerror ExternalCallFailed();\\nerror FunctionDoesNotExist();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n\\n function revertWith(bytes memory data) internal pure {\\n assembly {\\n let dataSize := mload(data) // Load the size of the data\\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\\n revert(dataPtr, dataSize) // Revert with the given data\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"solady/=lib/solady/src/\",\r\n \"permit2/=lib/Permit2/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"Permit2/=lib/Permit2/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"forge-gas-snapshot/=lib/Permit2/lib/forge-gas-snapshot/src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IAcrossSpokePool\",\"name\":\"_spokePool\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_wrappedNative\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"spokePool\",\"outputs\":[{\"internalType\":\"contract IAcrossSpokePool\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"receiverAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"refundAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"outputAmountPercent\",\"type\":\"uint64\"},{\"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\"}],\"internalType\":\"struct AcrossFacetV3.AcrossV3Data\",\"name\":\"_acrossData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaAcrossV3\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"receiverAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"refundAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"outputAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"outputAmountPercent\",\"type\":\"uint64\"},{\"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\"}],\"internalType\":\"struct AcrossFacetV3.AcrossV3Data\",\"name\":\"_acrossData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaAcrossV3\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"wrappedNative\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + ContractName: "AcrossFacetV3", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000005c7bcd6e7de5423a257d81b442095a1a6ced35c5000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/AcrossFacetV3.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IAcrossSpokePool } from \"../Interfaces/IAcrossSpokePool.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2 } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { InformationMismatch } from \"../Errors/GenericErrors.sol\";\n\n/// @title AcrossFacetV3\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through Across Protocol\n/// @custom:version 1.1.0\ncontract AcrossFacetV3 is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n /// @notice The contract address of the spoke pool on the source chain.\n IAcrossSpokePool public immutable spokePool;\n\n /// @notice The WETH address on the current chain.\n address public immutable wrappedNative;\n\n /// Types ///\n\n /// @param receiverAddress The address that will receive the token on dst chain (our Receiver contract or the user-defined receiver address)\n /// @param refundAddress The address that will be used for potential bridge refunds\n /// @param receivingAssetId The address of the token to be received at destination chain\n /// @param outputAmount The amount to be received at destination chain (after fees)\n /// @param outputAmountPercent The percentage of the output amount with 18 decimal precision (0.7550e18 = 75.50%, 0.99e18 = 99.00%)\n /// @param exclusiveRelayer This is the exclusive relayer who can fill the deposit before the exclusivity deadline.\n /// @param quoteTimestamp The timestamp of the Across quote that was used for this transaction\n /// @param fillDeadline The destination chain timestamp until which the order can be filled\n /// @param exclusivityDeadline The timestamp on the destination chain after which any relayer can fill the deposit\n /// @param message Arbitrary data that can be used to pass additional information to the recipient along with the tokens\n struct AcrossV3Data {\n address receiverAddress;\n address refundAddress;\n address receivingAssetId;\n uint256 outputAmount;\n uint64 outputAmountPercent;\n address exclusiveRelayer;\n uint32 quoteTimestamp;\n uint32 fillDeadline;\n uint32 exclusivityDeadline;\n bytes message;\n }\n\n /// Constructor ///\n\n /// @notice Initialize the contract.\n /// @param _spokePool The contract address of the spoke pool on the source chain.\n /// @param _wrappedNative The address of the wrapped native token on the source chain.\n constructor(IAcrossSpokePool _spokePool, address _wrappedNative) {\n spokePool = _spokePool;\n wrappedNative = _wrappedNative;\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via Across\n /// @param _bridgeData the core information needed for bridging\n /// @param _acrossData data specific to Across\n function startBridgeTokensViaAcrossV3(\n ILiFi.BridgeData memory _bridgeData,\n AcrossV3Data calldata _acrossData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n validateBridgeData(_bridgeData)\n doesNotContainSourceSwaps(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(_bridgeData, _acrossData);\n }\n\n /// @notice Performs a swap before bridging via Across\n /// @param _bridgeData the core information needed for bridging\n /// @param _swapData an array of swap related data for performing swaps before bridging\n /// @param _acrossData data specific to Across\n function swapAndStartBridgeTokensViaAcrossV3(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n AcrossV3Data calldata _acrossData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n validateBridgeData(_bridgeData)\n {\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n\n // Create modified across data with calculated output amount\n AcrossV3Data memory modifiedAcrossData = _acrossData;\n modifiedAcrossData.outputAmount =\n (_bridgeData.minAmount * _acrossData.outputAmountPercent) /\n 1e18;\n\n _startBridge(_bridgeData, modifiedAcrossData);\n }\n\n /// Internal Methods ///\n\n /// @dev Contains the business logic for the bridge via Across\n /// @param _bridgeData the core information needed for bridging\n /// @param _acrossData data specific to Across\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n AcrossV3Data memory _acrossData\n ) internal {\n // validate destination call flag\n if (_acrossData.message.length > 0 != _bridgeData.hasDestinationCall)\n revert InformationMismatch();\n\n // ensure that receiver addresses match in case of no destination call\n if (\n !_bridgeData.hasDestinationCall &&\n (_bridgeData.receiver != _acrossData.receiverAddress)\n ) revert InformationMismatch();\n\n // check if sendingAsset is native or ERC20\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // NATIVE\n spokePool.depositV3{ value: _bridgeData.minAmount }(\n _acrossData.refundAddress, // depositor (also acts as refund address in case release tx cannot be executed)\n _acrossData.receiverAddress, // recipient (on dst)\n wrappedNative, // inputToken\n _acrossData.receivingAssetId, // outputToken\n _bridgeData.minAmount, // inputAmount\n _acrossData.outputAmount, // outputAmount\n _bridgeData.destinationChainId,\n _acrossData.exclusiveRelayer,\n _acrossData.quoteTimestamp,\n _acrossData.fillDeadline,\n _acrossData.exclusivityDeadline,\n _acrossData.message\n );\n } else {\n // ERC20\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(spokePool),\n _bridgeData.minAmount\n );\n spokePool.depositV3(\n _acrossData.refundAddress, // depositor (also acts as refund address in case release tx cannot be executed)\n _acrossData.receiverAddress, // recipient (on dst)\n _bridgeData.sendingAssetId, // inputToken\n _acrossData.receivingAssetId, // outputToken\n _bridgeData.minAmount, // inputAmount\n _acrossData.outputAmount, // outputAmount\n _bridgeData.destinationChainId,\n _acrossData.exclusiveRelayer,\n _acrossData.quoteTimestamp,\n _acrossData.fillDeadline,\n _acrossData.exclusivityDeadline,\n _acrossData.message\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n}\n" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IAcrossSpokePool.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\ninterface IAcrossSpokePool {\n function deposit(\n address recipient, // Recipient address\n address originToken, // Address of the token\n uint256 amount, // Token amount\n uint256 destinationChainId, // ⛓ id\n int64 relayerFeePct, // see #Fees Calculation\n uint32 quoteTimestamp, // Timestamp for the quote creation\n bytes memory message, // Arbitrary data that can be used to pass additional information to the recipient along with the tokens.\n uint256 maxCount // Used to protect the depositor from frontrunning to guarantee their quote remains valid.\n ) external payable;\n\n function depositV3(\n address depositor,\n address recipient,\n address inputToken,\n address outputToken,\n uint256 inputAmount,\n uint256 outputAmount, // <-- replaces fees\n uint256 destinationChainId,\n address exclusiveRelayer,\n uint32 quoteTimestamp,\n uint32 fillDeadline,\n uint32 exclusivityDeadline,\n bytes calldata message\n ) external payable;\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @custom:version 1.0.1\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n address internal constant NON_EVM_ADDRESS =\n 0x11f111f111f111F111f111f111F111f111f111F1;\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n LibUtil.revertWith(res);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror DiamondIsPaused();\nerror ExternalCallFailed();\nerror FunctionDoesNotExist();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n\n function revertWith(bytes memory data) internal pure {\n assembly {\n let dataSize := mload(data) // Load the size of the data\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\n revert(dataPtr, dataSize) // Revert with the given data\n }\n }\n}\n" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "solady/=lib/solady/src/", + "permit2/=lib/Permit2/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "Permit2/=lib/Permit2/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "forge-gas-snapshot/=lib/Permit2/lib/forge-gas-snapshot/src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +1.1.0 + Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... -EmergencyPauseFacet +0x6f2baa7cd5f156ca1b132f7ff11e0fa2ad775f61 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/EmergencyPauseFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { LibDiamondLoupe } from \\\"../Libraries/LibDiamondLoupe.sol\\\";\\nimport { UnAuthorized, InvalidCallData, DiamondIsPaused } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IDiamondLoupe } from \\\"lifi/Interfaces/IDiamondLoupe.sol\\\";\\nimport { IDiamondCut } from \\\"lifi/Interfaces/IDiamondCut.sol\\\";\\nimport { DiamondCutFacet } from \\\"lifi/Facets/DiamondCutFacet.sol\\\";\\n\\n/// @title EmergencyPauseFacet (Admin only)\\n/// @author LI.FI (https://li.fi)\\n/// @notice Allows a LI.FI-owned and -controlled, non-multisig \\\"PauserWallet\\\" to remove a facet or pause the diamond in case of emergency\\n/// @custom:version 1.0.0\\n/// @dev Admin-Facet for emergency purposes only\\ncontract EmergencyPauseFacet {\\n /// Events ///\\n event EmergencyFacetRemoved(\\n address indexed facetAddress,\\n address indexed msgSender\\n );\\n event EmergencyPaused(address indexed msgSender);\\n event EmergencyUnpaused(address indexed msgSender);\\n\\n /// Errors ///\\n error FacetIsNotRegistered();\\n error NoFacetToPause();\\n\\n /// Storage ///\\n address public immutable pauserWallet;\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.facets.emergencyPauseFacet\\\");\\n address internal immutable _emergencyPauseFacetAddress;\\n\\n struct Storage {\\n IDiamondLoupe.Facet[] facets;\\n }\\n\\n /// Modifiers ///\\n modifier OnlyPauserWalletOrOwner() {\\n if (\\n msg.sender != pauserWallet &&\\n msg.sender != LibDiamond.contractOwner()\\n ) revert UnAuthorized();\\n _;\\n }\\n\\n /// Constructor ///\\n /// @param _pauserWallet The address of the wallet that can execute emergency facet removal actions\\n constructor(address _pauserWallet) {\\n pauserWallet = _pauserWallet;\\n _emergencyPauseFacetAddress = address(this);\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Removes the given facet from the diamond\\n /// @param _facetAddress The address of the facet that should be removed\\n /// @dev can only be executed by pauserWallet (non-multisig for fast response time) or by the diamond owner\\n function removeFacet(\\n address _facetAddress\\n ) external OnlyPauserWalletOrOwner {\\n // make sure that the EmergencyPauseFacet itself cannot be removed through this function\\n if (_facetAddress == _emergencyPauseFacetAddress)\\n revert InvalidCallData();\\n\\n // get function selectors for this facet\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n bytes4[] memory functionSelectors = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors;\\n\\n // do not continue if no registered function selectors were found\\n if (functionSelectors.length == 0) revert FacetIsNotRegistered();\\n\\n // make sure that DiamondCutFacet cannot be removed\\n if (functionSelectors[0] == DiamondCutFacet.diamondCut.selector)\\n revert InvalidCallData();\\n\\n // remove facet\\n LibDiamond.removeFunctions(address(0), functionSelectors);\\n\\n emit EmergencyFacetRemoved(_facetAddress, msg.sender);\\n }\\n\\n /// @notice Effectively pauses the diamond contract by overwriting the facetAddress-to-function-selector mappings in storage for all facets\\n /// and redirecting all function selectors to the EmergencyPauseFacet (this will remain as the only registered facet) so that\\n /// a meaningful error message will be returned when third parties try to call the diamond\\n /// @dev can only be executed by pauserWallet (non-multisig for fast response time) or by the diamond owner\\n /// @dev This function could potentially run out of gas if too many facets/function selectors are involved. We mitigate this issue by having a test on\\n /// @dev forked mainnet (which has most facets) that checks if the diamond can be paused\\n function pauseDiamond() external OnlyPauserWalletOrOwner {\\n Storage storage s = getStorage();\\n\\n // get a list of all facets that need to be removed (=all facets except EmergencyPauseFacet)\\n IDiamondLoupe.Facet[]\\n memory facets = _getAllFacetFunctionSelectorsToBeRemoved();\\n\\n // prevent invalid contract state\\n if (facets.length == 0) revert NoFacetToPause();\\n\\n // go through all facets\\n for (uint256 i; i < facets.length; ) {\\n // redirect all function selectors to this facet (i.e. to its fallback function with the DiamondIsPaused() error message)\\n LibDiamond.replaceFunctions(\\n _emergencyPauseFacetAddress,\\n facets[i].functionSelectors\\n );\\n\\n // write facet information to storage (so it can be easily reactivated later on)\\n s.facets.push(facets[i]);\\n\\n // gas-efficient way to increase loop counter\\n unchecked {\\n ++i;\\n }\\n }\\n\\n emit EmergencyPaused(msg.sender);\\n }\\n\\n /// @notice Unpauses the diamond contract by re-adding all facetAddress-to-function-selector mappings to storage\\n /// @dev can only be executed by diamond owner (multisig)\\n /// @param _blacklist The address(es) of facet(s) that should not be reactivated\\n function unpauseDiamond(address[] calldata _blacklist) external {\\n // make sure this function can only be called by the owner\\n LibDiamond.enforceIsContractOwner();\\n\\n // get all facets from storage\\n Storage storage s = getStorage();\\n\\n // iterate through all facets and reinstate the facet with its function selectors\\n for (uint256 i; i < s.facets.length; ) {\\n LibDiamond.replaceFunctions(\\n s.facets[i].facetAddress,\\n s.facets[i].functionSelectors\\n );\\n\\n // gas-efficient way to increase loop counter\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // go through blacklist and overwrite all function selectors with zero address\\n // It would be easier to not reinstate these facets in the first place but\\n // a) that would leave their function selectors associated with address of EmergencyPauseFacet (=> throws 'DiamondIsPaused() error when called)\\n // b) it consumes a lot of gas to check every facet address if it's part of the blacklist\\n bytes4[] memory currentSelectors;\\n for (uint256 i; i < _blacklist.length; ) {\\n currentSelectors = LibDiamondLoupe.facetFunctionSelectors(\\n _blacklist[i]\\n );\\n\\n // make sure that the DiamondCutFacet cannot be removed as this would make the diamond immutable\\n if (currentSelectors[0] == DiamondCutFacet.diamondCut.selector)\\n continue;\\n\\n // build FacetCut parameter\\n IDiamondCut.FacetCut[]\\n memory facetCut = new IDiamondCut.FacetCut[](1);\\n facetCut[0] = IDiamondCut.FacetCut({\\n facetAddress: address(0), // needs to be address(0) for removals\\n action: IDiamondCut.FacetCutAction.Remove,\\n functionSelectors: currentSelectors\\n });\\n\\n // remove facet and its selectors from diamond\\n LibDiamond.diamondCut(facetCut, address(0), \\\"\\\");\\n\\n // gas-efficient way to increase loop counter\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // free storage\\n delete s.facets;\\n\\n emit EmergencyUnpaused(msg.sender);\\n }\\n\\n /// INTERNAL HELPER FUNCTIONS\\n\\n function _getAllFacetFunctionSelectorsToBeRemoved()\\n internal\\n view\\n returns (IDiamondLoupe.Facet[] memory toBeRemoved)\\n {\\n // get a list of all registered facet addresses\\n IDiamondLoupe.Facet[] memory allFacets = LibDiamondLoupe.facets();\\n\\n // initiate return variable with allFacets length - 1 (since we will not remove the EmergencyPauseFacet)\\n toBeRemoved = new IDiamondLoupe.Facet[](allFacets.length - 1);\\n\\n // iterate through facets, copy every facet but EmergencyPauseFacet\\n uint256 toBeRemovedCounter;\\n for (uint256 i; i < allFacets.length; ) {\\n // if its not the EmergencyPauseFacet, copy to the return value variable\\n if (allFacets[i].facetAddress != _emergencyPauseFacetAddress) {\\n toBeRemoved[toBeRemovedCounter].facetAddress = allFacets[i]\\n .facetAddress;\\n toBeRemoved[toBeRemovedCounter].functionSelectors = allFacets[\\n i\\n ].functionSelectors;\\n\\n // gas-efficient way to increase counter\\n unchecked {\\n ++toBeRemovedCounter;\\n }\\n }\\n\\n // gas-efficient way to increase loop counter\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev fetch local storage\\n function getStorage() private pure returns (Storage storage s) {\\n bytes32 namespace = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n s.slot := namespace\\n }\\n }\\n\\n // this function will be called when the diamond is paused to return a meaningful error message instead of \\\"FunctionDoesNotExist\\\"\\n fallback() external payable {\\n revert DiamondIsPaused();\\n }\\n\\n // only added to silence compiler warnings that arose after adding the fallback function\\n receive() external payable {}\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] _diamondCut,\\n address _init,\\n bytes _calldata\\n );\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamondLoupe.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity 0.8.17;\\n\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { IDiamondLoupe } from \\\"../Interfaces/IDiamondLoupe.sol\\\";\\n\\n/// Library for DiamondLoupe functions (to avoid using external calls when using DiamondLoupe)\\nlibrary LibDiamondLoupe {\\n function facets()\\n internal\\n view\\n returns (IDiamondLoupe.Facet[] memory facets_)\\n {\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n uint256 numFacets = ds.facetAddresses.length;\\n facets_ = new IDiamondLoupe.Facet[](numFacets);\\n for (uint256 i = 0; i < numFacets; ) {\\n address facetAddress_ = ds.facetAddresses[i];\\n facets_[i].facetAddress = facetAddress_;\\n facets_[i].functionSelectors = ds\\n .facetFunctionSelectors[facetAddress_]\\n .functionSelectors;\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n function facetFunctionSelectors(\\n address _facet\\n ) internal view returns (bytes4[] memory facetFunctionSelectors_) {\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n facetFunctionSelectors_ = ds\\n .facetFunctionSelectors[_facet]\\n .functionSelectors;\\n }\\n\\n function facetAddresses()\\n internal\\n view\\n returns (address[] memory facetAddresses_)\\n {\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n facetAddresses_ = ds.facetAddresses;\\n }\\n\\n function facetAddress(\\n bytes4 _functionSelector\\n ) internal view returns (address facetAddress_) {\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n facetAddress_ = ds\\n .selectorToFacetAndPosition[_functionSelector]\\n .facetAddress;\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity 0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror DiamondIsPaused();\\nerror ExternalCallFailed();\\nerror FunctionDoesNotExist();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Interfaces/IDiamondLoupe.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity 0.8.17;\\n\\n// A loupe is a small magnifying glass used to look at diamonds.\\n// These functions look at diamonds\\ninterface IDiamondLoupe {\\n /// These functions are expected to be called frequently\\n /// by tools.\\n\\n struct Facet {\\n address facetAddress;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Gets all facet addresses and their four byte function selectors.\\n /// @return facets_ Facet\\n function facets() external view returns (Facet[] memory facets_);\\n\\n /// @notice Gets all the function selectors supported by a specific facet.\\n /// @param _facet The facet address.\\n /// @return facetFunctionSelectors_\\n function facetFunctionSelectors(\\n address _facet\\n ) external view returns (bytes4[] memory facetFunctionSelectors_);\\n\\n /// @notice Get all the facet addresses used by a diamond.\\n /// @return facetAddresses_\\n function facetAddresses()\\n external\\n view\\n returns (address[] memory facetAddresses_);\\n\\n /// @notice Gets the facet that supports the given selector.\\n /// @dev If facet is not found return address(0).\\n /// @param _functionSelector The function selector.\\n /// @return facetAddress_ The facet address.\\n function facetAddress(\\n bytes4 _functionSelector\\n ) external view returns (address facetAddress_);\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDiamondCut.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity 0.8.17;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\"\r\n },\r\n \"src/Facets/DiamondCutFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { IDiamondCut } from \\\"../Interfaces/IDiamondCut.sol\\\";\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\n\\n/// @title Diamond Cut Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Core EIP-2535 Facet for upgrading Diamond Proxies.\\n/// @custom:version 1.0.0\\ncontract DiamondCutFacet is IDiamondCut {\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external override {\\n LibDiamond.enforceIsContractOwner();\\n LibDiamond.diamondCut(_diamondCut, _init, _calldata);\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity 0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n\\n function revertWith(bytes memory data) internal pure {\\n assembly {\\n let dataSize := mload(data) // Load the size of the data\\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\\n revert(dataPtr, dataSize) // Revert with the given data\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity 0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"solady/=lib/solady/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_pauserWallet\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CalldataEmptyButInitNotZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DiamondIsPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FacetAddressIsNotZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FacetAddressIsZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FacetContainsNoCode\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FacetIsNotRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FunctionAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FunctionDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FunctionIsImmutable\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectFacetCutAction\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InitReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InitZeroButCalldataNotEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCallData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoFacetToPause\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSelectorsInFace\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyContractOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnAuthorized\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"}],\"name\":\"EmergencyFacetRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"}],\"name\":\"EmergencyPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"msgSender\",\"type\":\"address\"}],\"name\":\"EmergencyUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"pauseDiamond\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauserWallet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_facetAddress\",\"type\":\"address\"}],\"name\":\"removeFacet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_blacklist\",\"type\":\"address[]\"}],\"name\":\"unpauseDiamond\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", + ContractName: "EmergencyPauseFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "000000000000000000000000d38743b48d26743c0ec6898d699394fbc94657ee", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/EmergencyPauseFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { LibDiamondLoupe } from \"../Libraries/LibDiamondLoupe.sol\";\nimport { UnAuthorized, InvalidCallData, DiamondIsPaused } from \"../Errors/GenericErrors.sol\";\nimport { IDiamondLoupe } from \"lifi/Interfaces/IDiamondLoupe.sol\";\nimport { IDiamondCut } from \"lifi/Interfaces/IDiamondCut.sol\";\nimport { DiamondCutFacet } from \"lifi/Facets/DiamondCutFacet.sol\";\n\n/// @title EmergencyPauseFacet (Admin only)\n/// @author LI.FI (https://li.fi)\n/// @notice Allows a LI.FI-owned and -controlled, non-multisig \"PauserWallet\" to remove a facet or pause the diamond in case of emergency\n/// @custom:version 1.0.0\n/// @dev Admin-Facet for emergency purposes only\ncontract EmergencyPauseFacet {\n /// Events ///\n event EmergencyFacetRemoved(\n address indexed facetAddress,\n address indexed msgSender\n );\n event EmergencyPaused(address indexed msgSender);\n event EmergencyUnpaused(address indexed msgSender);\n\n /// Errors ///\n error FacetIsNotRegistered();\n error NoFacetToPause();\n\n /// Storage ///\n address public immutable pauserWallet;\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.facets.emergencyPauseFacet\");\n address internal immutable _emergencyPauseFacetAddress;\n\n struct Storage {\n IDiamondLoupe.Facet[] facets;\n }\n\n /// Modifiers ///\n modifier OnlyPauserWalletOrOwner() {\n if (\n msg.sender != pauserWallet &&\n msg.sender != LibDiamond.contractOwner()\n ) revert UnAuthorized();\n _;\n }\n\n /// Constructor ///\n /// @param _pauserWallet The address of the wallet that can execute emergency facet removal actions\n constructor(address _pauserWallet) {\n pauserWallet = _pauserWallet;\n _emergencyPauseFacetAddress = address(this);\n }\n\n /// External Methods ///\n\n /// @notice Removes the given facet from the diamond\n /// @param _facetAddress The address of the facet that should be removed\n /// @dev can only be executed by pauserWallet (non-multisig for fast response time) or by the diamond owner\n function removeFacet(\n address _facetAddress\n ) external OnlyPauserWalletOrOwner {\n // make sure that the EmergencyPauseFacet itself cannot be removed through this function\n if (_facetAddress == _emergencyPauseFacetAddress)\n revert InvalidCallData();\n\n // get function selectors for this facet\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n bytes4[] memory functionSelectors = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors;\n\n // do not continue if no registered function selectors were found\n if (functionSelectors.length == 0) revert FacetIsNotRegistered();\n\n // make sure that DiamondCutFacet cannot be removed\n if (functionSelectors[0] == DiamondCutFacet.diamondCut.selector)\n revert InvalidCallData();\n\n // remove facet\n LibDiamond.removeFunctions(address(0), functionSelectors);\n\n emit EmergencyFacetRemoved(_facetAddress, msg.sender);\n }\n\n /// @notice Effectively pauses the diamond contract by overwriting the facetAddress-to-function-selector mappings in storage for all facets\n /// and redirecting all function selectors to the EmergencyPauseFacet (this will remain as the only registered facet) so that\n /// a meaningful error message will be returned when third parties try to call the diamond\n /// @dev can only be executed by pauserWallet (non-multisig for fast response time) or by the diamond owner\n /// @dev This function could potentially run out of gas if too many facets/function selectors are involved. We mitigate this issue by having a test on\n /// @dev forked mainnet (which has most facets) that checks if the diamond can be paused\n function pauseDiamond() external OnlyPauserWalletOrOwner {\n Storage storage s = getStorage();\n\n // get a list of all facets that need to be removed (=all facets except EmergencyPauseFacet)\n IDiamondLoupe.Facet[]\n memory facets = _getAllFacetFunctionSelectorsToBeRemoved();\n\n // prevent invalid contract state\n if (facets.length == 0) revert NoFacetToPause();\n\n // go through all facets\n for (uint256 i; i < facets.length; ) {\n // redirect all function selectors to this facet (i.e. to its fallback function with the DiamondIsPaused() error message)\n LibDiamond.replaceFunctions(\n _emergencyPauseFacetAddress,\n facets[i].functionSelectors\n );\n\n // write facet information to storage (so it can be easily reactivated later on)\n s.facets.push(facets[i]);\n\n // gas-efficient way to increase loop counter\n unchecked {\n ++i;\n }\n }\n\n emit EmergencyPaused(msg.sender);\n }\n\n /// @notice Unpauses the diamond contract by re-adding all facetAddress-to-function-selector mappings to storage\n /// @dev can only be executed by diamond owner (multisig)\n /// @param _blacklist The address(es) of facet(s) that should not be reactivated\n function unpauseDiamond(address[] calldata _blacklist) external {\n // make sure this function can only be called by the owner\n LibDiamond.enforceIsContractOwner();\n\n // get all facets from storage\n Storage storage s = getStorage();\n\n // iterate through all facets and reinstate the facet with its function selectors\n for (uint256 i; i < s.facets.length; ) {\n LibDiamond.replaceFunctions(\n s.facets[i].facetAddress,\n s.facets[i].functionSelectors\n );\n\n // gas-efficient way to increase loop counter\n unchecked {\n ++i;\n }\n }\n\n // go through blacklist and overwrite all function selectors with zero address\n // It would be easier to not reinstate these facets in the first place but\n // a) that would leave their function selectors associated with address of EmergencyPauseFacet (=> throws 'DiamondIsPaused() error when called)\n // b) it consumes a lot of gas to check every facet address if it's part of the blacklist\n bytes4[] memory currentSelectors;\n for (uint256 i; i < _blacklist.length; ) {\n currentSelectors = LibDiamondLoupe.facetFunctionSelectors(\n _blacklist[i]\n );\n\n // make sure that the DiamondCutFacet cannot be removed as this would make the diamond immutable\n if (currentSelectors[0] == DiamondCutFacet.diamondCut.selector)\n continue;\n\n // build FacetCut parameter\n IDiamondCut.FacetCut[]\n memory facetCut = new IDiamondCut.FacetCut[](1);\n facetCut[0] = IDiamondCut.FacetCut({\n facetAddress: address(0), // needs to be address(0) for removals\n action: IDiamondCut.FacetCutAction.Remove,\n functionSelectors: currentSelectors\n });\n\n // remove facet and its selectors from diamond\n LibDiamond.diamondCut(facetCut, address(0), \"\");\n\n // gas-efficient way to increase loop counter\n unchecked {\n ++i;\n }\n }\n\n // free storage\n delete s.facets;\n\n emit EmergencyUnpaused(msg.sender);\n }\n\n /// INTERNAL HELPER FUNCTIONS\n\n function _getAllFacetFunctionSelectorsToBeRemoved()\n internal\n view\n returns (IDiamondLoupe.Facet[] memory toBeRemoved)\n {\n // get a list of all registered facet addresses\n IDiamondLoupe.Facet[] memory allFacets = LibDiamondLoupe.facets();\n\n // initiate return variable with allFacets length - 1 (since we will not remove the EmergencyPauseFacet)\n toBeRemoved = new IDiamondLoupe.Facet[](allFacets.length - 1);\n\n // iterate through facets, copy every facet but EmergencyPauseFacet\n uint256 toBeRemovedCounter;\n for (uint256 i; i < allFacets.length; ) {\n // if its not the EmergencyPauseFacet, copy to the return value variable\n if (allFacets[i].facetAddress != _emergencyPauseFacetAddress) {\n toBeRemoved[toBeRemovedCounter].facetAddress = allFacets[i]\n .facetAddress;\n toBeRemoved[toBeRemovedCounter].functionSelectors = allFacets[\n i\n ].functionSelectors;\n\n // gas-efficient way to increase counter\n unchecked {\n ++toBeRemovedCounter;\n }\n }\n\n // gas-efficient way to increase loop counter\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev fetch local storage\n function getStorage() private pure returns (Storage storage s) {\n bytes32 namespace = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n s.slot := namespace\n }\n }\n\n // this function will be called when the diamond is paused to return a meaningful error message instead of \"FunctionDoesNotExist\"\n fallback() external payable {\n revert DiamondIsPaused();\n }\n\n // only added to silence compiler warnings that arose after adding the fallback function\n receive() external payable {}\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] _diamondCut,\n address _init,\n bytes _calldata\n );\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Libraries/LibDiamondLoupe.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity 0.8.17;\n\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { IDiamondLoupe } from \"../Interfaces/IDiamondLoupe.sol\";\n\n/// Library for DiamondLoupe functions (to avoid using external calls when using DiamondLoupe)\nlibrary LibDiamondLoupe {\n function facets()\n internal\n view\n returns (IDiamondLoupe.Facet[] memory facets_)\n {\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n uint256 numFacets = ds.facetAddresses.length;\n facets_ = new IDiamondLoupe.Facet[](numFacets);\n for (uint256 i = 0; i < numFacets; ) {\n address facetAddress_ = ds.facetAddresses[i];\n facets_[i].facetAddress = facetAddress_;\n facets_[i].functionSelectors = ds\n .facetFunctionSelectors[facetAddress_]\n .functionSelectors;\n unchecked {\n ++i;\n }\n }\n }\n\n function facetFunctionSelectors(\n address _facet\n ) internal view returns (bytes4[] memory facetFunctionSelectors_) {\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n facetFunctionSelectors_ = ds\n .facetFunctionSelectors[_facet]\n .functionSelectors;\n }\n\n function facetAddresses()\n internal\n view\n returns (address[] memory facetAddresses_)\n {\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n facetAddresses_ = ds.facetAddresses;\n }\n\n function facetAddress(\n bytes4 _functionSelector\n ) internal view returns (address facetAddress_) {\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n facetAddress_ = ds\n .selectorToFacetAndPosition[_functionSelector]\n .facetAddress;\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity 0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror DiamondIsPaused();\nerror ExternalCallFailed();\nerror FunctionDoesNotExist();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Interfaces/IDiamondLoupe.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity 0.8.17;\n\n// A loupe is a small magnifying glass used to look at diamonds.\n// These functions look at diamonds\ninterface IDiamondLoupe {\n /// These functions are expected to be called frequently\n /// by tools.\n\n struct Facet {\n address facetAddress;\n bytes4[] functionSelectors;\n }\n\n /// @notice Gets all facet addresses and their four byte function selectors.\n /// @return facets_ Facet\n function facets() external view returns (Facet[] memory facets_);\n\n /// @notice Gets all the function selectors supported by a specific facet.\n /// @param _facet The facet address.\n /// @return facetFunctionSelectors_\n function facetFunctionSelectors(\n address _facet\n ) external view returns (bytes4[] memory facetFunctionSelectors_);\n\n /// @notice Get all the facet addresses used by a diamond.\n /// @return facetAddresses_\n function facetAddresses()\n external\n view\n returns (address[] memory facetAddresses_);\n\n /// @notice Gets the facet that supports the given selector.\n /// @dev If facet is not found return address(0).\n /// @param _functionSelector The function selector.\n /// @return facetAddress_ The facet address.\n function facetAddress(\n bytes4 _functionSelector\n ) external view returns (address facetAddress_);\n}\n" + }, + "src/Interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity 0.8.17;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "src/Facets/DiamondCutFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { IDiamondCut } from \"../Interfaces/IDiamondCut.sol\";\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\n\n/// @title Diamond Cut Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Core EIP-2535 Facet for upgrading Diamond Proxies.\n/// @custom:version 1.0.0\ncontract DiamondCutFacet is IDiamondCut {\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external override {\n LibDiamond.enforceIsContractOwner();\n LibDiamond.diamondCut(_diamondCut, _init, _calldata);\n }\n}\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity 0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n\n function revertWith(bytes memory data) internal pure {\n assembly {\n let dataSize := mload(data) // Load the size of the data\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\n revert(dataPtr, dataSize) // Revert with the given data\n }\n }\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity 0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "solady/=lib/solady/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... /GasZipFacet +0xf5c923a087fb3c554579e2dd10ab6e37e0f6f849 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/GasZipFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { IGasZip } from \\\"../Interfaces/IGasZip.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2 } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { SafeTransferLib } from \\\"solady/utils/SafeTransferLib.sol\\\";\\nimport { InvalidCallData, CannotBridgeToSameNetwork, InvalidAmount } from \\\"lifi/Errors/GenericErrors.sol\\\";\\n\\n/// @title GasZipFacet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality to swap ERC20 tokens to native and deposit them to the gas.zip protocol (https://www.gas.zip/)\\n/// @custom:version 2.0.0\\ncontract GasZipFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n using SafeTransferLib for address;\\n\\n error OnlyNativeAllowed();\\n error TooManyChainIds();\\n\\n /// State ///\\n address public constant NON_EVM_RECEIVER_IDENTIFIER =\\n 0x11f111f111f111F111f111f111F111f111f111F1;\\n IGasZip public immutable gasZipRouter;\\n\\n /// Constructor ///\\n constructor(address _gasZipRouter) {\\n gasZipRouter = IGasZip(_gasZipRouter);\\n }\\n\\n /// @notice Bridges tokens using the gas.zip protocol\\n /// @dev this function only supports native flow. For ERC20 flows this facet should be used as a protocol step instead\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _gasZipData contains information which chains and address gas should be sent to\\n function startBridgeTokensViaGasZip(\\n ILiFi.BridgeData memory _bridgeData,\\n IGasZip.GasZipData calldata _gasZipData\\n )\\n external\\n payable\\n nonReentrant\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n {\\n // this function / path shall only be used for native assets\\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId))\\n revert OnlyNativeAllowed();\\n\\n // make sure that msg.value matches the to-be-deposited amount\\n if (msg.value != _bridgeData.minAmount) revert InvalidAmount();\\n\\n // deposit native to Gas.zip\\n _startBridge(_bridgeData, _gasZipData);\\n }\\n\\n /// @notice Performs one or multiple actions (e.g. fee collection, swapping) that must end with the native token before depositing to the gas.zip protocol\\n /// @param _bridgeData The core information needed for depositing\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _gasZipData contains information which chains and address gas should be sent to\\n function swapAndStartBridgeTokensViaGasZip(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n IGasZip.GasZipData calldata _gasZipData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n {\\n // make sure that the output of the last swap step is native\\n if (\\n !LibAsset.isNativeAsset(\\n _swapData[_swapData.length - 1].receivingAssetId\\n )\\n ) revert InvalidCallData();\\n\\n // deposit and swap ERC20 tokens to native\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender)\\n );\\n\\n // deposit native to Gas.zip\\n _startBridge(_bridgeData, _gasZipData);\\n }\\n\\n /// @dev Contains the business logic for depositing to GasZip protocol\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _gasZipData contains information which chains and address gas should be sent to\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n IGasZip.GasZipData calldata _gasZipData\\n ) internal {\\n // make sure receiver address has a value to prevent potential loss of funds\\n if (_gasZipData.receiverAddress == bytes32(0))\\n revert InvalidCallData();\\n\\n // validate that receiverAddress matches with bridgeData in case of EVM target chain\\n if (\\n _bridgeData.receiver != NON_EVM_RECEIVER_IDENTIFIER &&\\n _gasZipData.receiverAddress !=\\n bytes32(uint256(uint160(_bridgeData.receiver)))\\n ) revert InvalidCallData();\\n\\n // validate bridgeData\\n // make sure destinationChainId is of a different network\\n if (_bridgeData.destinationChainId == block.chainid)\\n revert CannotBridgeToSameNetwork();\\n\\n // We are depositing to a new contract that supports deposits for EVM chains + Solana (therefore 'receiver' address is bytes32)\\n gasZipRouter.deposit{ value: _bridgeData.minAmount }(\\n _gasZipData.destinationChains,\\n _gasZipData.receiverAddress\\n );\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// @dev Returns a value that signals to Gas.zip to which chains gas should be sent in equal parts\\n /// @param _chainIds a list of Gas.zip-specific chainIds (not the original chainIds), see https://dev.gas.zip/gas/chain-support/outbound\\n function getDestinationChainsValue(\\n uint8[] calldata _chainIds\\n ) external pure returns (uint256 destinationChains) {\\n uint256 length = _chainIds.length;\\n\\n if (length > 32) revert TooManyChainIds();\\n\\n for (uint256 i; i < length; ++i) {\\n // Shift destinationChains left by 8 bits and add the next chainID\\n destinationChains =\\n (destinationChains << 8) |\\n uint256(_chainIds[i]);\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Interfaces/IGasZip.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity 0.8.17;\\n\\n/// @title Interface for GasZip\\n/// @author LI.FI (https://li.fi)\\ninterface IGasZip {\\n /// @dev GasZip-specific bridge data\\n /// @param receiverAddress the address on destination chain(s) where gas should be sent to\\n /// @param destinationChains a value that represents a list of chains to which gas should be distributed (see https://dev.gas.zip/gas/code-examples/deposit for more details)\\n struct GasZipData {\\n bytes32 receiverAddress;\\n // EVM addresses need to be padded with trailing 0s, e.g.:\\n // 0x391E7C679D29BD940D63BE94AD22A25D25B5A604000000000000000000000000 (correct)\\n // 0x000000000000000000000000391E7C679D29BD940D63BE94AD22A25D25B5A604 (incorrect)\\n uint256 destinationChains;\\n }\\n\\n function deposit(uint256 destinationChains, bytes32 to) external payable;\\n}\\n\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n LibUtil.revertWith(res);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"lib/solady/src/utils/SafeTransferLib.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)\\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\\n/// @author Permit2 operations from (https://github.com/Uniswap/permit2/blob/main/src/libraries/Permit2Lib.sol)\\n///\\n/// @dev Note:\\n/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.\\n/// - For ERC20s, this implementation won't check that a token has code,\\n/// responsibility is delegated to the caller.\\nlibrary SafeTransferLib {\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* CUSTOM ERRORS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev The ETH transfer has failed.\\n error ETHTransferFailed();\\n\\n /// @dev The ERC20 `transferFrom` has failed.\\n error TransferFromFailed();\\n\\n /// @dev The ERC20 `transfer` has failed.\\n error TransferFailed();\\n\\n /// @dev The ERC20 `approve` has failed.\\n error ApproveFailed();\\n\\n /// @dev The Permit2 operation has failed.\\n error Permit2Failed();\\n\\n /// @dev The Permit2 amount must be less than `2**160 - 1`.\\n error Permit2AmountOverflow();\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* CONSTANTS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.\\n uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;\\n\\n /// @dev Suggested gas stipend for contract receiving ETH to perform a few\\n /// storage reads and writes, but low enough to prevent griefing.\\n uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;\\n\\n /// @dev The unique EIP-712 domain domain separator for the DAI token contract.\\n bytes32 internal constant DAI_DOMAIN_SEPARATOR =\\n 0xdbb8cf42e1ecb028be3f3dbc922e1d878b963f411dc388ced501601c60f7c6f7;\\n\\n /// @dev The address for the WETH9 contract on Ethereum mainnet.\\n address internal constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\\n\\n /// @dev The canonical Permit2 address.\\n /// [Github](https://github.com/Uniswap/permit2)\\n /// [Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3)\\n address internal constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* ETH OPERATIONS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.\\n //\\n // The regular variants:\\n // - Forwards all remaining gas to the target.\\n // - Reverts if the target reverts.\\n // - Reverts if the current contract has insufficient balance.\\n //\\n // The force variants:\\n // - Forwards with an optional gas stipend\\n // (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).\\n // - If the target reverts, or if the gas stipend is exhausted,\\n // creates a temporary contract to force send the ETH via `SELFDESTRUCT`.\\n // Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.\\n // - Reverts if the current contract has insufficient balance.\\n //\\n // The try variants:\\n // - Forwards with a mandatory gas stipend.\\n // - Instead of reverting, returns whether the transfer succeeded.\\n\\n /// @dev Sends `amount` (in wei) ETH to `to`.\\n function safeTransferETH(address to, uint256 amount) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {\\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n }\\n }\\n\\n /// @dev Sends all the ETH in the current contract to `to`.\\n function safeTransferAllETH(address to) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // Transfer all the ETH and check if it succeeded or not.\\n if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n }\\n }\\n\\n /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\\n function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n if lt(selfbalance(), amount) {\\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) {\\n mstore(0x00, to) // Store the address in scratch space.\\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\\n if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\\n }\\n }\\n }\\n\\n /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.\\n function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\\n mstore(0x00, to) // Store the address in scratch space.\\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\\n if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\\n }\\n }\\n }\\n\\n /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.\\n function forceSafeTransferETH(address to, uint256 amount) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n if lt(selfbalance(), amount) {\\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) {\\n mstore(0x00, to) // Store the address in scratch space.\\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\\n if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\\n }\\n }\\n }\\n\\n /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.\\n function forceSafeTransferAllETH(address to) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n // forgefmt: disable-next-item\\n if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\\n mstore(0x00, to) // Store the address in scratch space.\\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\\n if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\\n }\\n }\\n }\\n\\n /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\\n function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)\\n internal\\n returns (bool success)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)\\n }\\n }\\n\\n /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.\\n function trySafeTransferAllETH(address to, uint256 gasStipend)\\n internal\\n returns (bool success)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)\\n }\\n }\\n\\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\\n /* ERC20 OPERATIONS */\\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\\n\\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\\n /// Reverts upon failure.\\n ///\\n /// The `from` account must have at least `amount` approved for\\n /// the current contract to manage.\\n function safeTransferFrom(address token, address from, address to, uint256 amount) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40) // Cache the free memory pointer.\\n mstore(0x60, amount) // Store the `amount` argument.\\n mstore(0x40, to) // Store the `to` argument.\\n mstore(0x2c, shl(96, from)) // Store the `from` argument.\\n mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.\\n // Perform the transfer, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x60, 0) // Restore the zero slot to zero.\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\\n ///\\n /// The `from` account must have at least `amount` approved for the current contract to manage.\\n function trySafeTransferFrom(address token, address from, address to, uint256 amount)\\n internal\\n returns (bool success)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40) // Cache the free memory pointer.\\n mstore(0x60, amount) // Store the `amount` argument.\\n mstore(0x40, to) // Store the `to` argument.\\n mstore(0x2c, shl(96, from)) // Store the `from` argument.\\n mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.\\n success :=\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\\n )\\n mstore(0x60, 0) // Restore the zero slot to zero.\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /// @dev Sends all of ERC20 `token` from `from` to `to`.\\n /// Reverts upon failure.\\n ///\\n /// The `from` account must have their entire balance approved for the current contract to manage.\\n function safeTransferAllFrom(address token, address from, address to)\\n internal\\n returns (uint256 amount)\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40) // Cache the free memory pointer.\\n mstore(0x40, to) // Store the `to` argument.\\n mstore(0x2c, shl(96, from)) // Store the `from` argument.\\n mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.\\n // Read the balance, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\\n staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.\\n amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.\\n // Perform the transfer, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x60, 0) // Restore the zero slot to zero.\\n mstore(0x40, m) // Restore the free memory pointer.\\n }\\n }\\n\\n /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.\\n /// Reverts upon failure.\\n function safeTransfer(address token, address to, uint256 amount) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x14, to) // Store the `to` argument.\\n mstore(0x34, amount) // Store the `amount` argument.\\n mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.\\n // Perform the transfer, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\\n }\\n }\\n\\n /// @dev Sends all of ERC20 `token` from the current contract to `to`.\\n /// Reverts upon failure.\\n function safeTransferAll(address token, address to) internal returns (uint256 amount) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.\\n mstore(0x20, address()) // Store the address of the current contract.\\n // Read the balance, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\\n staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x14, to) // Store the `to` argument.\\n amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.\\n mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.\\n // Perform the transfer, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\\n }\\n }\\n\\n /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.\\n /// Reverts upon failure.\\n function safeApprove(address token, address to, uint256 amount) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x14, to) // Store the `to` argument.\\n mstore(0x34, amount) // Store the `amount` argument.\\n mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\\n // Perform the approval, reverting upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.\\n revert(0x1c, 0x04)\\n }\\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\\n }\\n }\\n\\n /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.\\n /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,\\n /// then retries the approval again (some tokens, e.g. USDT, requires this).\\n /// Reverts upon failure.\\n function safeApproveWithRetry(address token, address to, uint256 amount) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x14, to) // Store the `to` argument.\\n mstore(0x34, amount) // Store the `amount` argument.\\n mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\\n // Perform the approval, retrying upon failure.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x34, 0) // Store 0 for the `amount`.\\n mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\\n pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval.\\n mstore(0x34, amount) // Store back the original `amount`.\\n // Retry the approval, reverting upon failure.\\n if iszero(\\n and(\\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\\n )\\n ) {\\n mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.\\n revert(0x1c, 0x04)\\n }\\n }\\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\\n }\\n }\\n\\n /// @dev Returns the amount of ERC20 `token` owned by `account`.\\n /// Returns zero if the `token` does not exist.\\n function balanceOf(address token, address account) internal view returns (uint256 amount) {\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore(0x14, account) // Store the `account` argument.\\n mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.\\n amount :=\\n mul( // The arguments of `mul` are evaluated from right to left.\\n mload(0x20),\\n and( // The arguments of `and` are evaluated from right to left.\\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\\n staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)\\n )\\n )\\n }\\n }\\n\\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\\n /// If the initial attempt fails, try to use Permit2 to transfer the token.\\n /// Reverts upon failure.\\n ///\\n /// The `from` account must have at least `amount` approved for the current contract to manage.\\n function safeTransferFrom2(address token, address from, address to, uint256 amount) internal {\\n if (!trySafeTransferFrom(token, from, to, amount)) {\\n permit2TransferFrom(token, from, to, amount);\\n }\\n }\\n\\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to` via Permit2.\\n /// Reverts upon failure.\\n function permit2TransferFrom(address token, address from, address to, uint256 amount)\\n internal\\n {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40)\\n mstore(add(m, 0x74), shr(96, shl(96, token)))\\n mstore(add(m, 0x54), amount)\\n mstore(add(m, 0x34), to)\\n mstore(add(m, 0x20), shl(96, from))\\n // `transferFrom(address,address,uint160,address)`.\\n mstore(m, 0x36c78516000000000000000000000000)\\n let p := PERMIT2\\n let exists := eq(chainid(), 1)\\n if iszero(exists) { exists := iszero(iszero(extcodesize(p))) }\\n if iszero(and(call(gas(), p, 0, add(m, 0x10), 0x84, codesize(), 0x00), exists)) {\\n mstore(0x00, 0x7939f4248757f0fd) // `TransferFromFailed()` or `Permit2AmountOverflow()`.\\n revert(add(0x18, shl(2, iszero(iszero(shr(160, amount))))), 0x04)\\n }\\n }\\n }\\n\\n /// @dev Permit a user to spend a given amount of\\n /// another user's tokens via native EIP-2612 permit if possible, falling\\n /// back to Permit2 if native permit fails or is not implemented on the token.\\n function permit2(\\n address token,\\n address owner,\\n address spender,\\n uint256 amount,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n bool success;\\n /// @solidity memory-safe-assembly\\n assembly {\\n for {} shl(96, xor(token, WETH9)) {} {\\n mstore(0x00, 0x3644e515) // `DOMAIN_SEPARATOR()`.\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n lt(iszero(mload(0x00)), eq(returndatasize(), 0x20)), // Returns 1 non-zero word.\\n // Gas stipend to limit gas burn for tokens that don't refund gas when\\n // an non-existing function is called. 5K should be enough for a SLOAD.\\n staticcall(5000, token, 0x1c, 0x04, 0x00, 0x20)\\n )\\n ) { break }\\n // After here, we can be sure that token is a contract.\\n let m := mload(0x40)\\n mstore(add(m, 0x34), spender)\\n mstore(add(m, 0x20), shl(96, owner))\\n mstore(add(m, 0x74), deadline)\\n if eq(mload(0x00), DAI_DOMAIN_SEPARATOR) {\\n mstore(0x14, owner)\\n mstore(0x00, 0x7ecebe00000000000000000000000000) // `nonces(address)`.\\n mstore(add(m, 0x94), staticcall(gas(), token, 0x10, 0x24, add(m, 0x54), 0x20))\\n mstore(m, 0x8fcbaf0c000000000000000000000000) // `IDAIPermit.permit`.\\n // `nonces` is already at `add(m, 0x54)`.\\n // `1` is already stored at `add(m, 0x94)`.\\n mstore(add(m, 0xb4), and(0xff, v))\\n mstore(add(m, 0xd4), r)\\n mstore(add(m, 0xf4), s)\\n success := call(gas(), token, 0, add(m, 0x10), 0x104, codesize(), 0x00)\\n break\\n }\\n mstore(m, 0xd505accf000000000000000000000000) // `IERC20Permit.permit`.\\n mstore(add(m, 0x54), amount)\\n mstore(add(m, 0x94), and(0xff, v))\\n mstore(add(m, 0xb4), r)\\n mstore(add(m, 0xd4), s)\\n success := call(gas(), token, 0, add(m, 0x10), 0xe4, codesize(), 0x00)\\n break\\n }\\n }\\n if (!success) simplePermit2(token, owner, spender, amount, deadline, v, r, s);\\n }\\n\\n /// @dev Simple permit on the Permit2 contract.\\n function simplePermit2(\\n address token,\\n address owner,\\n address spender,\\n uint256 amount,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n /// @solidity memory-safe-assembly\\n assembly {\\n let m := mload(0x40)\\n mstore(m, 0x927da105) // `allowance(address,address,address)`.\\n {\\n let addressMask := shr(96, not(0))\\n mstore(add(m, 0x20), and(addressMask, owner))\\n mstore(add(m, 0x40), and(addressMask, token))\\n mstore(add(m, 0x60), and(addressMask, spender))\\n mstore(add(m, 0xc0), and(addressMask, spender))\\n }\\n let p := mul(PERMIT2, iszero(shr(160, amount)))\\n if iszero(\\n and( // The arguments of `and` are evaluated from right to left.\\n gt(returndatasize(), 0x5f), // Returns 3 words: `amount`, `expiration`, `nonce`.\\n staticcall(gas(), p, add(m, 0x1c), 0x64, add(m, 0x60), 0x60)\\n )\\n ) {\\n mstore(0x00, 0x6b836e6b8757f0fd) // `Permit2Failed()` or `Permit2AmountOverflow()`.\\n revert(add(0x18, shl(2, iszero(p))), 0x04)\\n }\\n mstore(m, 0x2b67b570) // `Permit2.permit` (PermitSingle variant).\\n // `owner` is already `add(m, 0x20)`.\\n // `token` is already at `add(m, 0x40)`.\\n mstore(add(m, 0x60), amount)\\n mstore(add(m, 0x80), 0xffffffffffff) // `expiration = type(uint48).max`.\\n // `nonce` is already at `add(m, 0xa0)`.\\n // `spender` is already at `add(m, 0xc0)`.\\n mstore(add(m, 0xe0), deadline)\\n mstore(add(m, 0x100), 0x100) // `signature` offset.\\n mstore(add(m, 0x120), 0x41) // `signature` length.\\n mstore(add(m, 0x140), r)\\n mstore(add(m, 0x160), s)\\n mstore(add(m, 0x180), shl(248, v))\\n if iszero(call(gas(), p, 0, add(m, 0x1c), 0x184, codesize(), 0x00)) {\\n mstore(0x00, 0x6b836e6b) // `Permit2Failed()`.\\n revert(0x1c, 0x04)\\n }\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror DiamondIsPaused();\\nerror ExternalCallFailed();\\nerror FunctionDoesNotExist();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n\\n function revertWith(bytes memory data) internal pure {\\n assembly {\\n let dataSize := mload(data) // Load the size of the data\\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\\n revert(dataPtr, dataSize) // Revert with the given data\\n }\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"solady/=lib/solady/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_gasZipRouter\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCallData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyNativeAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyChainIds\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"NON_EVM_RECEIVER_IDENTIFIER\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gasZipRouter\",\"outputs\":[{\"internalType\":\"contract IGasZip\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8[]\",\"name\":\"_chainIds\",\"type\":\"uint8[]\"}],\"name\":\"getDestinationChainsValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"destinationChains\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"receiverAddress\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"destinationChains\",\"type\":\"uint256\"}],\"internalType\":\"struct IGasZip.GasZipData\",\"name\":\"_gasZipData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaGasZip\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"receiverAddress\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"destinationChains\",\"type\":\"uint256\"}],\"internalType\":\"struct IGasZip.GasZipData\",\"name\":\"_gasZipData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaGasZip\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "GasZipFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "0000000000000000000000002a37d63eadfe4b4682a3c28c1c2cd4f109cc2762", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/GasZipFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { IGasZip } from \"../Interfaces/IGasZip.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2 } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { SafeTransferLib } from \"solady/utils/SafeTransferLib.sol\";\nimport { InvalidCallData, CannotBridgeToSameNetwork, InvalidAmount } from \"lifi/Errors/GenericErrors.sol\";\n\n/// @title GasZipFacet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality to swap ERC20 tokens to native and deposit them to the gas.zip protocol (https://www.gas.zip/)\n/// @custom:version 2.0.0\ncontract GasZipFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n using SafeTransferLib for address;\n\n error OnlyNativeAllowed();\n error TooManyChainIds();\n\n /// State ///\n address public constant NON_EVM_RECEIVER_IDENTIFIER =\n 0x11f111f111f111F111f111f111F111f111f111F1;\n IGasZip public immutable gasZipRouter;\n\n /// Constructor ///\n constructor(address _gasZipRouter) {\n gasZipRouter = IGasZip(_gasZipRouter);\n }\n\n /// @notice Bridges tokens using the gas.zip protocol\n /// @dev this function only supports native flow. For ERC20 flows this facet should be used as a protocol step instead\n /// @param _bridgeData The core information needed for bridging\n /// @param _gasZipData contains information which chains and address gas should be sent to\n function startBridgeTokensViaGasZip(\n ILiFi.BridgeData memory _bridgeData,\n IGasZip.GasZipData calldata _gasZipData\n )\n external\n payable\n nonReentrant\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n {\n // this function / path shall only be used for native assets\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId))\n revert OnlyNativeAllowed();\n\n // make sure that msg.value matches the to-be-deposited amount\n if (msg.value != _bridgeData.minAmount) revert InvalidAmount();\n\n // deposit native to Gas.zip\n _startBridge(_bridgeData, _gasZipData);\n }\n\n /// @notice Performs one or multiple actions (e.g. fee collection, swapping) that must end with the native token before depositing to the gas.zip protocol\n /// @param _bridgeData The core information needed for depositing\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _gasZipData contains information which chains and address gas should be sent to\n function swapAndStartBridgeTokensViaGasZip(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n IGasZip.GasZipData calldata _gasZipData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n {\n // make sure that the output of the last swap step is native\n if (\n !LibAsset.isNativeAsset(\n _swapData[_swapData.length - 1].receivingAssetId\n )\n ) revert InvalidCallData();\n\n // deposit and swap ERC20 tokens to native\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender)\n );\n\n // deposit native to Gas.zip\n _startBridge(_bridgeData, _gasZipData);\n }\n\n /// @dev Contains the business logic for depositing to GasZip protocol\n /// @param _bridgeData The core information needed for bridging\n /// @param _gasZipData contains information which chains and address gas should be sent to\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n IGasZip.GasZipData calldata _gasZipData\n ) internal {\n // make sure receiver address has a value to prevent potential loss of funds\n if (_gasZipData.receiverAddress == bytes32(0))\n revert InvalidCallData();\n\n // validate that receiverAddress matches with bridgeData in case of EVM target chain\n if (\n _bridgeData.receiver != NON_EVM_RECEIVER_IDENTIFIER &&\n _gasZipData.receiverAddress !=\n bytes32(uint256(uint160(_bridgeData.receiver)))\n ) revert InvalidCallData();\n\n // validate bridgeData\n // make sure destinationChainId is of a different network\n if (_bridgeData.destinationChainId == block.chainid)\n revert CannotBridgeToSameNetwork();\n\n // We are depositing to a new contract that supports deposits for EVM chains + Solana (therefore 'receiver' address is bytes32)\n gasZipRouter.deposit{ value: _bridgeData.minAmount }(\n _gasZipData.destinationChains,\n _gasZipData.receiverAddress\n );\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// @dev Returns a value that signals to Gas.zip to which chains gas should be sent in equal parts\n /// @param _chainIds a list of Gas.zip-specific chainIds (not the original chainIds), see https://dev.gas.zip/gas/chain-support/outbound\n function getDestinationChainsValue(\n uint8[] calldata _chainIds\n ) external pure returns (uint256 destinationChains) {\n uint256 length = _chainIds.length;\n\n if (length > 32) revert TooManyChainIds();\n\n for (uint256 i; i < length; ++i) {\n // Shift destinationChains left by 8 bits and add the next chainID\n destinationChains =\n (destinationChains << 8) |\n uint256(_chainIds[i]);\n }\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Interfaces/IGasZip.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity 0.8.17;\n\n/// @title Interface for GasZip\n/// @author LI.FI (https://li.fi)\ninterface IGasZip {\n /// @dev GasZip-specific bridge data\n /// @param receiverAddress the address on destination chain(s) where gas should be sent to\n /// @param destinationChains a value that represents a list of chains to which gas should be distributed (see https://dev.gas.zip/gas/code-examples/deposit for more details)\n struct GasZipData {\n bytes32 receiverAddress;\n // EVM addresses need to be padded with trailing 0s, e.g.:\n // 0x391E7C679D29BD940D63BE94AD22A25D25B5A604000000000000000000000000 (correct)\n // 0x000000000000000000000000391E7C679D29BD940D63BE94AD22A25D25B5A604 (incorrect)\n uint256 destinationChains;\n }\n\n function deposit(uint256 destinationChains, bytes32 to) external payable;\n}\n" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n LibUtil.revertWith(res);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.safeApprove(IERC20(assetId), spender, 0);\n SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "lib/solady/src/utils/SafeTransferLib.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @author Permit2 operations from (https://github.com/Uniswap/permit2/blob/main/src/libraries/Permit2Lib.sol)\n///\n/// @dev Note:\n/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.\n/// - For ERC20s, this implementation won't check that a token has code,\n/// responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CUSTOM ERRORS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev The ETH transfer has failed.\n error ETHTransferFailed();\n\n /// @dev The ERC20 `transferFrom` has failed.\n error TransferFromFailed();\n\n /// @dev The ERC20 `transfer` has failed.\n error TransferFailed();\n\n /// @dev The ERC20 `approve` has failed.\n error ApproveFailed();\n\n /// @dev The Permit2 operation has failed.\n error Permit2Failed();\n\n /// @dev The Permit2 amount must be less than `2**160 - 1`.\n error Permit2AmountOverflow();\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CONSTANTS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.\n uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;\n\n /// @dev Suggested gas stipend for contract receiving ETH to perform a few\n /// storage reads and writes, but low enough to prevent griefing.\n uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;\n\n /// @dev The unique EIP-712 domain domain separator for the DAI token contract.\n bytes32 internal constant DAI_DOMAIN_SEPARATOR =\n 0xdbb8cf42e1ecb028be3f3dbc922e1d878b963f411dc388ced501601c60f7c6f7;\n\n /// @dev The address for the WETH9 contract on Ethereum mainnet.\n address internal constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n\n /// @dev The canonical Permit2 address.\n /// [Github](https://github.com/Uniswap/permit2)\n /// [Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3)\n address internal constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* ETH OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.\n //\n // The regular variants:\n // - Forwards all remaining gas to the target.\n // - Reverts if the target reverts.\n // - Reverts if the current contract has insufficient balance.\n //\n // The force variants:\n // - Forwards with an optional gas stipend\n // (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).\n // - If the target reverts, or if the gas stipend is exhausted,\n // creates a temporary contract to force send the ETH via `SELFDESTRUCT`.\n // Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.\n // - Reverts if the current contract has insufficient balance.\n //\n // The try variants:\n // - Forwards with a mandatory gas stipend.\n // - Instead of reverting, returns whether the transfer succeeded.\n\n /// @dev Sends `amount` (in wei) ETH to `to`.\n function safeTransferETH(address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Sends all the ETH in the current contract to `to`.\n function safeTransferAllETH(address to) internal {\n /// @solidity memory-safe-assembly\n assembly {\n // Transfer all the ETH and check if it succeeded or not.\n if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\n function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {\n /// @solidity memory-safe-assembly\n assembly {\n if lt(selfbalance(), amount) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, to) // Store the address in scratch space.\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\n }\n }\n }\n\n /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.\n function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {\n /// @solidity memory-safe-assembly\n assembly {\n if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, to) // Store the address in scratch space.\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\n }\n }\n }\n\n /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.\n function forceSafeTransferETH(address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n if lt(selfbalance(), amount) {\n mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n revert(0x1c, 0x04)\n }\n if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, to) // Store the address in scratch space.\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\n }\n }\n }\n\n /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.\n function forceSafeTransferAllETH(address to) internal {\n /// @solidity memory-safe-assembly\n assembly {\n // forgefmt: disable-next-item\n if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\n mstore(0x00, to) // Store the address in scratch space.\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\n }\n }\n }\n\n /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\n function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)\n internal\n returns (bool success)\n {\n /// @solidity memory-safe-assembly\n assembly {\n success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)\n }\n }\n\n /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.\n function trySafeTransferAllETH(address to, uint256 gasStipend)\n internal\n returns (bool success)\n {\n /// @solidity memory-safe-assembly\n assembly {\n success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* ERC20 OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\n /// Reverts upon failure.\n ///\n /// The `from` account must have at least `amount` approved for\n /// the current contract to manage.\n function safeTransferFrom(address token, address from, address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, amount) // Store the `amount` argument.\n mstore(0x40, to) // Store the `to` argument.\n mstore(0x2c, shl(96, from)) // Store the `from` argument.\n mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.\n // Perform the transfer, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\n )\n ) {\n mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x60, 0) // Restore the zero slot to zero.\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\n ///\n /// The `from` account must have at least `amount` approved for the current contract to manage.\n function trySafeTransferFrom(address token, address from, address to, uint256 amount)\n internal\n returns (bool success)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x60, amount) // Store the `amount` argument.\n mstore(0x40, to) // Store the `to` argument.\n mstore(0x2c, shl(96, from)) // Store the `from` argument.\n mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.\n success :=\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\n )\n mstore(0x60, 0) // Restore the zero slot to zero.\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Sends all of ERC20 `token` from `from` to `to`.\n /// Reverts upon failure.\n ///\n /// The `from` account must have their entire balance approved for the current contract to manage.\n function safeTransferAllFrom(address token, address from, address to)\n internal\n returns (uint256 amount)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n mstore(0x40, to) // Store the `to` argument.\n mstore(0x2c, shl(96, from)) // Store the `from` argument.\n mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.\n // Read the balance, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)\n )\n ) {\n mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.\n amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.\n // Perform the transfer, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\n )\n ) {\n mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x60, 0) // Restore the zero slot to zero.\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.\n /// Reverts upon failure.\n function safeTransfer(address token, address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x14, to) // Store the `to` argument.\n mstore(0x34, amount) // Store the `amount` argument.\n mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.\n // Perform the transfer, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n )\n ) {\n mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\n }\n }\n\n /// @dev Sends all of ERC20 `token` from the current contract to `to`.\n /// Reverts upon failure.\n function safeTransferAll(address token, address to) internal returns (uint256 amount) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.\n mstore(0x20, address()) // Store the address of the current contract.\n // Read the balance, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)\n )\n ) {\n mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x14, to) // Store the `to` argument.\n amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.\n mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.\n // Perform the transfer, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n )\n ) {\n mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\n }\n }\n\n /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.\n /// Reverts upon failure.\n function safeApprove(address token, address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x14, to) // Store the `to` argument.\n mstore(0x34, amount) // Store the `amount` argument.\n mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\n // Perform the approval, reverting upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n )\n ) {\n mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.\n revert(0x1c, 0x04)\n }\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\n }\n }\n\n /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.\n /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,\n /// then retries the approval again (some tokens, e.g. USDT, requires this).\n /// Reverts upon failure.\n function safeApproveWithRetry(address token, address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x14, to) // Store the `to` argument.\n mstore(0x34, amount) // Store the `amount` argument.\n mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\n // Perform the approval, retrying upon failure.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n )\n ) {\n mstore(0x34, 0) // Store 0 for the `amount`.\n mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\n pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval.\n mstore(0x34, amount) // Store back the original `amount`.\n // Retry the approval, reverting upon failure.\n if iszero(\n and(\n or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n )\n ) {\n mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.\n revert(0x1c, 0x04)\n }\n }\n mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\n }\n }\n\n /// @dev Returns the amount of ERC20 `token` owned by `account`.\n /// Returns zero if the `token` does not exist.\n function balanceOf(address token, address account) internal view returns (uint256 amount) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x14, account) // Store the `account` argument.\n mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.\n amount :=\n mul( // The arguments of `mul` are evaluated from right to left.\n mload(0x20),\n and( // The arguments of `and` are evaluated from right to left.\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)\n )\n )\n }\n }\n\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\n /// If the initial attempt fails, try to use Permit2 to transfer the token.\n /// Reverts upon failure.\n ///\n /// The `from` account must have at least `amount` approved for the current contract to manage.\n function safeTransferFrom2(address token, address from, address to, uint256 amount) internal {\n if (!trySafeTransferFrom(token, from, to, amount)) {\n permit2TransferFrom(token, from, to, amount);\n }\n }\n\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to` via Permit2.\n /// Reverts upon failure.\n function permit2TransferFrom(address token, address from, address to, uint256 amount)\n internal\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n mstore(add(m, 0x74), shr(96, shl(96, token)))\n mstore(add(m, 0x54), amount)\n mstore(add(m, 0x34), to)\n mstore(add(m, 0x20), shl(96, from))\n // `transferFrom(address,address,uint160,address)`.\n mstore(m, 0x36c78516000000000000000000000000)\n let p := PERMIT2\n let exists := eq(chainid(), 1)\n if iszero(exists) { exists := iszero(iszero(extcodesize(p))) }\n if iszero(and(call(gas(), p, 0, add(m, 0x10), 0x84, codesize(), 0x00), exists)) {\n mstore(0x00, 0x7939f4248757f0fd) // `TransferFromFailed()` or `Permit2AmountOverflow()`.\n revert(add(0x18, shl(2, iszero(iszero(shr(160, amount))))), 0x04)\n }\n }\n }\n\n /// @dev Permit a user to spend a given amount of\n /// another user's tokens via native EIP-2612 permit if possible, falling\n /// back to Permit2 if native permit fails or is not implemented on the token.\n function permit2(\n address token,\n address owner,\n address spender,\n uint256 amount,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n bool success;\n /// @solidity memory-safe-assembly\n assembly {\n for {} shl(96, xor(token, WETH9)) {} {\n mstore(0x00, 0x3644e515) // `DOMAIN_SEPARATOR()`.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n lt(iszero(mload(0x00)), eq(returndatasize(), 0x20)), // Returns 1 non-zero word.\n // Gas stipend to limit gas burn for tokens that don't refund gas when\n // an non-existing function is called. 5K should be enough for a SLOAD.\n staticcall(5000, token, 0x1c, 0x04, 0x00, 0x20)\n )\n ) { break }\n // After here, we can be sure that token is a contract.\n let m := mload(0x40)\n mstore(add(m, 0x34), spender)\n mstore(add(m, 0x20), shl(96, owner))\n mstore(add(m, 0x74), deadline)\n if eq(mload(0x00), DAI_DOMAIN_SEPARATOR) {\n mstore(0x14, owner)\n mstore(0x00, 0x7ecebe00000000000000000000000000) // `nonces(address)`.\n mstore(add(m, 0x94), staticcall(gas(), token, 0x10, 0x24, add(m, 0x54), 0x20))\n mstore(m, 0x8fcbaf0c000000000000000000000000) // `IDAIPermit.permit`.\n // `nonces` is already at `add(m, 0x54)`.\n // `1` is already stored at `add(m, 0x94)`.\n mstore(add(m, 0xb4), and(0xff, v))\n mstore(add(m, 0xd4), r)\n mstore(add(m, 0xf4), s)\n success := call(gas(), token, 0, add(m, 0x10), 0x104, codesize(), 0x00)\n break\n }\n mstore(m, 0xd505accf000000000000000000000000) // `IERC20Permit.permit`.\n mstore(add(m, 0x54), amount)\n mstore(add(m, 0x94), and(0xff, v))\n mstore(add(m, 0xb4), r)\n mstore(add(m, 0xd4), s)\n success := call(gas(), token, 0, add(m, 0x10), 0xe4, codesize(), 0x00)\n break\n }\n }\n if (!success) simplePermit2(token, owner, spender, amount, deadline, v, r, s);\n }\n\n /// @dev Simple permit on the Permit2 contract.\n function simplePermit2(\n address token,\n address owner,\n address spender,\n uint256 amount,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40)\n mstore(m, 0x927da105) // `allowance(address,address,address)`.\n {\n let addressMask := shr(96, not(0))\n mstore(add(m, 0x20), and(addressMask, owner))\n mstore(add(m, 0x40), and(addressMask, token))\n mstore(add(m, 0x60), and(addressMask, spender))\n mstore(add(m, 0xc0), and(addressMask, spender))\n }\n let p := mul(PERMIT2, iszero(shr(160, amount)))\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n gt(returndatasize(), 0x5f), // Returns 3 words: `amount`, `expiration`, `nonce`.\n staticcall(gas(), p, add(m, 0x1c), 0x64, add(m, 0x60), 0x60)\n )\n ) {\n mstore(0x00, 0x6b836e6b8757f0fd) // `Permit2Failed()` or `Permit2AmountOverflow()`.\n revert(add(0x18, shl(2, iszero(p))), 0x04)\n }\n mstore(m, 0x2b67b570) // `Permit2.permit` (PermitSingle variant).\n // `owner` is already `add(m, 0x20)`.\n // `token` is already at `add(m, 0x40)`.\n mstore(add(m, 0x60), amount)\n mstore(add(m, 0x80), 0xffffffffffff) // `expiration = type(uint48).max`.\n // `nonce` is already at `add(m, 0xa0)`.\n // `spender` is already at `add(m, 0xc0)`.\n mstore(add(m, 0xe0), deadline)\n mstore(add(m, 0x100), 0x100) // `signature` offset.\n mstore(add(m, 0x120), 0x41) // `signature` length.\n mstore(add(m, 0x140), r)\n mstore(add(m, 0x160), s)\n mstore(add(m, 0x180), shl(248, v))\n if iszero(call(gas(), p, 0, add(m, 0x1c), 0x184, codesize(), 0x00)) {\n mstore(0x00, 0x6b836e6b) // `Permit2Failed()`.\n revert(0x1c, 0x04)\n }\n }\n }\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror DiamondIsPaused();\nerror ExternalCallFailed();\nerror FunctionDoesNotExist();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n\n function revertWith(bytes memory data) internal pure {\n assembly {\n let dataSize := mload(data) // Load the size of the data\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\n revert(dataPtr, dataSize) // Revert with the given data\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/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" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "solady/=lib/solady/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +2.0.0 + Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... |DeBridgeDlnFacet +0x18c85b940c29ecc3c210ea40a5b6d91f5aee2803 +{ + SourceCode: "{{\r\n \"language\": \"Solidity\",\r\n \"sources\": {\r\n \"src/Facets/DeBridgeDlnFacet.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { LibAsset, IERC20 } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { ReentrancyGuard } from \\\"../Helpers/ReentrancyGuard.sol\\\";\\nimport { SwapperV2 } from \\\"../Helpers/SwapperV2.sol\\\";\\nimport { Validatable } from \\\"../Helpers/Validatable.sol\\\";\\nimport { IDlnSource } from \\\"../Interfaces/IDlnSource.sol\\\";\\nimport { NotInitialized } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title DeBridgeDLN Facet\\n/// @author LI.FI (https://li.fi)\\n/// @notice Provides functionality for bridging through DeBridge DLN\\n/// @custom:version 1.0.0\\ncontract DeBridgeDlnFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\\n /// Storage ///\\n\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.facets.debridgedln\\\");\\n uint32 internal constant REFERRAL_CODE = 30729;\\n address internal constant NON_EVM_ADDRESS =\\n 0x11f111f111f111F111f111f111F111f111f111F1;\\n IDlnSource public immutable dlnSource;\\n\\n /// Types ///\\n\\n /// @param receivingAssetId The address of the asset to receive\\n /// @param receiver The address of the receiver\\n /// @param minAmountOut The minimum amount to receive on the destination chain\\n struct DeBridgeDlnData {\\n bytes receivingAssetId;\\n bytes receiver;\\n bytes orderAuthorityDst;\\n uint256 minAmountOut;\\n }\\n\\n struct Storage {\\n mapping(uint256 => uint256) deBridgeChainId;\\n bool initialized;\\n }\\n\\n struct ChainIdConfig {\\n uint256 chainId;\\n uint256 deBridgeChainId;\\n }\\n\\n /// Errors ///\\n\\n error UnknownDeBridgeChain();\\n error EmptyNonEVMAddress();\\n error InvalidConfig();\\n\\n /// Events ///\\n\\n event DeBridgeInitialized(ChainIdConfig[] chainIdConfigs);\\n\\n event DlnOrderCreated(bytes32 indexed orderId);\\n\\n event DeBridgeChainIdSet(uint256 indexed chainId, uint256 deBridgeChainId);\\n\\n event BridgeToNonEVMChain(\\n bytes32 indexed transactionId,\\n uint256 indexed destinationChainId,\\n bytes receiver\\n );\\n\\n /// Modifiers ///\\n\\n modifier onlyValidReceiverAddress(DeBridgeDlnData calldata _deBridgeData) {\\n // Ensure nonEVMAddress is not empty\\n if (_deBridgeData.receiver.length == 0) {\\n revert EmptyNonEVMAddress();\\n }\\n _;\\n }\\n\\n /// Constructor ///\\n\\n /// @notice Constructor for the contract.\\n /// @param _dlnSource The address of the DLN order creation contract\\n constructor(IDlnSource _dlnSource) {\\n dlnSource = _dlnSource;\\n }\\n\\n /// Init ///\\n\\n /// @notice Initialize local variables for the DeBridgeDln Facet\\n /// @param chainIdConfigs Chain Id configuration data\\n function initDeBridgeDln(\\n ChainIdConfig[] calldata chainIdConfigs\\n ) external {\\n if (chainIdConfigs.length == 0) revert InvalidConfig();\\n LibDiamond.enforceIsContractOwner();\\n\\n Storage storage sm = getStorage();\\n\\n for (uint256 i = 0; i < chainIdConfigs.length; i++) {\\n sm.deBridgeChainId[chainIdConfigs[i].chainId] = chainIdConfigs[i]\\n .deBridgeChainId;\\n }\\n\\n sm.initialized = true;\\n emit DeBridgeInitialized(chainIdConfigs);\\n }\\n\\n /// External Methods ///\\n\\n /// @notice Bridges tokens via DeBridgeDLN\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _deBridgeData Data specific to DeBridgeDLN\\n function startBridgeTokensViaDeBridgeDln(\\n ILiFi.BridgeData memory _bridgeData,\\n DeBridgeDlnData calldata _deBridgeData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n validateBridgeData(_bridgeData)\\n onlyValidReceiverAddress(_deBridgeData)\\n doesNotContainSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n {\\n LibAsset.depositAsset(\\n _bridgeData.sendingAssetId,\\n _bridgeData.minAmount\\n );\\n _startBridge(\\n _bridgeData,\\n _deBridgeData,\\n dlnSource.globalFixedNativeFee()\\n );\\n }\\n\\n /// @notice Performs a swap before bridging via DeBridgeDLN\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _swapData An array of swap related data for performing swaps before bridging\\n /// @param _deBridgeData Data specific to DeBridgeDLN\\n function swapAndStartBridgeTokensViaDeBridgeDln(\\n ILiFi.BridgeData memory _bridgeData,\\n LibSwap.SwapData[] calldata _swapData,\\n DeBridgeDlnData calldata _deBridgeData\\n )\\n external\\n payable\\n nonReentrant\\n refundExcessNative(payable(msg.sender))\\n containsSourceSwaps(_bridgeData)\\n doesNotContainDestinationCalls(_bridgeData)\\n validateBridgeData(_bridgeData)\\n onlyValidReceiverAddress(_deBridgeData)\\n {\\n uint256 fee = dlnSource.globalFixedNativeFee();\\n address assetId = _bridgeData.sendingAssetId;\\n _bridgeData.minAmount = _depositAndSwap(\\n _bridgeData.transactionId,\\n _bridgeData.minAmount,\\n _swapData,\\n payable(msg.sender),\\n LibAsset.isNativeAsset(assetId) ? 0 : fee\\n );\\n _startBridge(_bridgeData, _deBridgeData, fee);\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Contains the business logic for the bridge via DeBridgeDLN\\n /// @param _bridgeData The core information needed for bridging\\n /// @param _deBridgeData Data specific to DeBridgeDLN\\n function _startBridge(\\n ILiFi.BridgeData memory _bridgeData,\\n DeBridgeDlnData calldata _deBridgeData,\\n uint256 _fee\\n ) internal {\\n IDlnSource.OrderCreation memory orderCreation = IDlnSource\\n .OrderCreation({\\n giveTokenAddress: _bridgeData.sendingAssetId,\\n giveAmount: _bridgeData.minAmount,\\n takeTokenAddress: _deBridgeData.receivingAssetId,\\n takeAmount: _deBridgeData.minAmountOut,\\n takeChainId: getDeBridgeChainId(\\n _bridgeData.destinationChainId\\n ),\\n receiverDst: _deBridgeData.receiver,\\n givePatchAuthoritySrc: msg.sender,\\n orderAuthorityAddressDst: _deBridgeData.orderAuthorityDst,\\n allowedTakerDst: \\\"\\\",\\n externalCall: \\\"\\\",\\n allowedCancelBeneficiarySrc: abi.encodePacked(msg.sender)\\n });\\n\\n bytes32 orderId;\\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n // Give the DLN Source approval to bridge tokens\\n LibAsset.maxApproveERC20(\\n IERC20(_bridgeData.sendingAssetId),\\n address(dlnSource),\\n _bridgeData.minAmount\\n );\\n\\n orderId = dlnSource.createOrder{ value: _fee }(\\n orderCreation,\\n \\\"\\\",\\n REFERRAL_CODE,\\n \\\"\\\"\\n );\\n } else {\\n orderCreation.giveAmount = orderCreation.giveAmount - _fee;\\n orderId = dlnSource.createOrder{ value: _bridgeData.minAmount }(\\n orderCreation,\\n \\\"\\\",\\n REFERRAL_CODE,\\n \\\"\\\"\\n );\\n }\\n\\n emit DlnOrderCreated(orderId);\\n\\n if (_bridgeData.receiver == NON_EVM_ADDRESS) {\\n emit BridgeToNonEVMChain(\\n _bridgeData.transactionId,\\n _bridgeData.destinationChainId,\\n _deBridgeData.receiver\\n );\\n }\\n\\n emit LiFiTransferStarted(_bridgeData);\\n }\\n\\n /// Mappings management ///\\n\\n /// @notice Sets the DeBridge chain ID for a given chain ID\\n /// @param _chainId uint256 of the chain ID\\n /// @param _deBridgeChainId uint256 of the DeBridge chain ID\\n /// @dev This is used to map a chain ID to its DeBridge chain ID\\n function setDeBridgeChainId(\\n uint256 _chainId,\\n uint256 _deBridgeChainId\\n ) external {\\n LibDiamond.enforceIsContractOwner();\\n Storage storage sm = getStorage();\\n\\n if (!sm.initialized) {\\n revert NotInitialized();\\n }\\n\\n sm.deBridgeChainId[_chainId] = _deBridgeChainId;\\n emit DeBridgeChainIdSet(_chainId, _deBridgeChainId);\\n }\\n\\n /// @notice Gets the DeBridge chain ID for a given chain ID\\n /// @param _chainId uint256 of the chain ID\\n /// @return uint256 of the DeBridge chain ID\\n function getDeBridgeChainId(\\n uint256 _chainId\\n ) public view returns (uint256) {\\n Storage storage sm = getStorage();\\n uint256 chainId = sm.deBridgeChainId[_chainId];\\n if (chainId == 0) revert UnknownDeBridgeChain();\\n return chainId;\\n }\\n\\n /// @dev fetch local storage\\n function getStorage() private pure returns (Storage storage s) {\\n bytes32 namespace = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n s.slot := namespace\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/ILiFi.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\ninterface ILiFi {\\n /// Structs ///\\n\\n struct BridgeData {\\n bytes32 transactionId;\\n string bridge;\\n string integrator;\\n address referrer;\\n address sendingAssetId;\\n address receiver;\\n uint256 minAmount;\\n uint256 destinationChainId;\\n bool hasSourceSwaps;\\n bool hasDestinationCall;\\n }\\n\\n /// Events ///\\n\\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\\n\\n event LiFiTransferCompleted(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiTransferRecovered(\\n bytes32 indexed transactionId,\\n address receivingAssetId,\\n address receiver,\\n uint256 amount,\\n uint256 timestamp\\n );\\n\\n event LiFiGenericSwapCompleted(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address receiver,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n\\n // Deprecated but kept here to include in ABI to parse historic events\\n event LiFiSwappedGeneric(\\n bytes32 indexed transactionId,\\n string integrator,\\n string referrer,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount\\n );\\n}\\n\"\r\n },\r\n \"src/Libraries/LibDiamond.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.17;\\n\\n// import { IDiamondCut } from \\\"../Interfaces/LibDiamond.sol\\\";\\nimport { LibDiamond } from \\\"../Libraries/LibDiamond.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { OnlyContractOwner } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// Implementation of EIP-2535 Diamond Standard\\n/// https://eips.ethereum.org/EIPS/eip-2535\\nlibrary LibDiamond {\\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n // Diamond specific errors\\n error IncorrectFacetCutAction();\\n error NoSelectorsInFace();\\n error FunctionAlreadyExists();\\n error FacetAddressIsZero();\\n error FacetAddressIsNotZero();\\n error FacetContainsNoCode();\\n error FunctionDoesNotExist();\\n error FunctionIsImmutable();\\n error InitZeroButCalldataNotEmpty();\\n error CalldataEmptyButInitNotZero();\\n error InitReverted();\\n // ----------------\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n if (msg.sender != diamondStorage().contractOwner)\\n revert OnlyContractOwner();\\n }\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\\n LibDiamond.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == LibDiamond.FacetCutAction.Add) {\\n addFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == LibDiamond.FacetCutAction.Replace) {\\n replaceFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else if (action == LibDiamond.FacetCutAction.Remove) {\\n removeFunctions(\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n } else {\\n revert IncorrectFacetCutAction();\\n }\\n unchecked {\\n ++facetIndex;\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\\n revert FunctionAlreadyExists();\\n }\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function replaceFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsZero();\\n }\\n uint96 selectorPosition = uint96(\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\\n );\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n if (oldFacetAddress == _facetAddress) {\\n revert FunctionAlreadyExists();\\n }\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n unchecked {\\n ++selectorPosition;\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function removeFunctions(\\n address _facetAddress,\\n bytes4[] memory _functionSelectors\\n ) internal {\\n if (_functionSelectors.length == 0) {\\n revert NoSelectorsInFace();\\n }\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n if (!LibUtil.isZeroAddress(_facetAddress)) {\\n revert FacetAddressIsNotZero();\\n }\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _functionSelectors.length;\\n\\n ) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds\\n .selectorToFacetAndPosition[selector]\\n .facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n unchecked {\\n ++selectorIndex;\\n }\\n }\\n }\\n\\n function addFacet(\\n DiamondStorage storage ds,\\n address _facetAddress\\n ) internal {\\n enforceHasContractCode(_facetAddress);\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\\n .facetAddresses\\n .length;\\n ds.facetAddresses.push(_facetAddress);\\n }\\n\\n function addFunction(\\n DiamondStorage storage ds,\\n bytes4 _selector,\\n uint96 _selectorPosition,\\n address _facetAddress\\n ) internal {\\n ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\\n _selector\\n );\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(\\n DiamondStorage storage ds,\\n address _facetAddress,\\n bytes4 _selector\\n ) internal {\\n if (LibUtil.isZeroAddress(_facetAddress)) {\\n revert FunctionDoesNotExist();\\n }\\n // an immutable function is a function defined directly in a diamond\\n if (_facetAddress == address(this)) {\\n revert FunctionIsImmutable();\\n }\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds\\n .selectorToFacetAndPosition[_selector]\\n .functionSelectorPosition;\\n uint256 lastSelectorPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors\\n .length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds\\n .facetFunctionSelectors[_facetAddress]\\n .functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\\n selectorPosition\\n ] = lastSelector;\\n ds\\n .selectorToFacetAndPosition[lastSelector]\\n .functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[\\n lastFacetAddressPosition\\n ];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds\\n .facetFunctionSelectors[lastFacetAddress]\\n .facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds\\n .facetFunctionSelectors[_facetAddress]\\n .facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n if (LibUtil.isZeroAddress(_init)) {\\n if (_calldata.length != 0) {\\n revert InitZeroButCalldataNotEmpty();\\n }\\n } else {\\n if (_calldata.length == 0) {\\n revert CalldataEmptyButInitNotZero();\\n }\\n if (_init != address(this)) {\\n enforceHasContractCode(_init);\\n }\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert InitReverted();\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract) internal view {\\n uint256 contractSize;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n if (contractSize == 0) {\\n revert FacetContainsNoCode();\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibAsset.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\npragma solidity ^0.8.17;\\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \\\"../Errors/GenericErrors.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { LibSwap } from \\\"./LibSwap.sol\\\";\\n\\n/// @title LibAsset\\n/// @custom:version 1.0.2\\n/// @notice This library contains helpers for dealing with onchain transfers\\n/// of assets, including accounting for the native asset `assetId`\\n/// conventions and any noncompliant ERC20 transfers\\nlibrary LibAsset {\\n uint256 private constant MAX_UINT = type(uint256).max;\\n\\n address internal constant NULL_ADDRESS = address(0);\\n\\n address internal constant NON_EVM_ADDRESS =\\n 0x11f111f111f111F111f111f111F111f111f111F1;\\n\\n /// @dev All native assets use the empty address for their asset id\\n /// by convention\\n\\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\\n\\n /// @notice Gets the balance of the inheriting contract for the given asset\\n /// @param assetId The asset identifier to get the balance of\\n /// @return Balance held by contracts using this library\\n function getOwnBalance(address assetId) internal view returns (uint256) {\\n return\\n isNativeAsset(assetId)\\n ? address(this).balance\\n : IERC20(assetId).balanceOf(address(this));\\n }\\n\\n /// @notice Transfers ether from the inheriting contract to a given\\n /// recipient\\n /// @param recipient Address to send ether to\\n /// @param amount Amount to send to given recipient\\n function transferNativeAsset(\\n address payable recipient,\\n uint256 amount\\n ) private {\\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\\n if (amount > address(this).balance)\\n revert InsufficientBalance(amount, address(this).balance);\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n if (!success) revert NativeAssetTransferFailed();\\n }\\n\\n /// @notice If the current allowance is insufficient, the allowance for a given spender\\n /// is set to MAX_UINT.\\n /// @param assetId Token address to transfer\\n /// @param spender Address to give spend approval to\\n /// @param amount Amount to approve for spending\\n function maxApproveERC20(\\n IERC20 assetId,\\n address spender,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(address(assetId))) {\\n return;\\n }\\n if (spender == NULL_ADDRESS) {\\n revert NullAddrIsNotAValidSpender();\\n }\\n\\n if (assetId.allowance(address(this), spender) < amount) {\\n SafeERC20.forceApprove(IERC20(assetId), spender, MAX_UINT);\\n }\\n }\\n\\n /// @notice Transfers tokens from the inheriting contract to a given\\n /// recipient\\n /// @param assetId Token address to transfer\\n /// @param recipient Address to send token to\\n /// @param amount Amount to send to given recipient\\n function transferERC20(\\n address assetId,\\n address recipient,\\n uint256 amount\\n ) private {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (recipient == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\\n if (amount > assetBalance) {\\n revert InsufficientBalance(amount, assetBalance);\\n }\\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\\n }\\n\\n /// @notice Transfers tokens from a sender to a given recipient\\n /// @param assetId Token address to transfer\\n /// @param from Address of sender/owner\\n /// @param to Address of recipient/spender\\n /// @param amount Amount to transfer from owner to spender\\n function transferFromERC20(\\n address assetId,\\n address from,\\n address to,\\n uint256 amount\\n ) internal {\\n if (isNativeAsset(assetId)) {\\n revert NullAddrIsNotAnERC20Token();\\n }\\n if (to == NULL_ADDRESS) {\\n revert NoTransferToNullAddress();\\n }\\n\\n IERC20 asset = IERC20(assetId);\\n uint256 prevBalance = asset.balanceOf(to);\\n SafeERC20.safeTransferFrom(asset, from, to, amount);\\n if (asset.balanceOf(to) - prevBalance != amount) {\\n revert InvalidAmount();\\n }\\n }\\n\\n function depositAsset(address assetId, uint256 amount) internal {\\n if (amount == 0) revert InvalidAmount();\\n if (isNativeAsset(assetId)) {\\n if (msg.value < amount) revert InvalidAmount();\\n } else {\\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\\n if (balance < amount) revert InsufficientBalance(amount, balance);\\n transferFromERC20(assetId, msg.sender, address(this), amount);\\n }\\n }\\n\\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\\n for (uint256 i = 0; i < swaps.length; ) {\\n LibSwap.SwapData calldata swap = swaps[i];\\n if (swap.requiresDeposit) {\\n depositAsset(swap.sendingAssetId, swap.fromAmount);\\n }\\n unchecked {\\n i++;\\n }\\n }\\n }\\n\\n /// @notice Determines whether the given assetId is the native asset\\n /// @param assetId The asset identifier to evaluate\\n /// @return Boolean indicating if the asset is the native asset\\n function isNativeAsset(address assetId) internal pure returns (bool) {\\n return assetId == NATIVE_ASSETID;\\n }\\n\\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\\n /// some recipient. Should handle all non-compliant return value\\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\\n /// @param assetId Asset id for transfer (address(0) for native asset,\\n /// token address for erc20s)\\n /// @param recipient Address to send asset to\\n /// @param amount Amount to send to given recipient\\n function transferAsset(\\n address assetId,\\n address payable recipient,\\n uint256 amount\\n ) internal {\\n isNativeAsset(assetId)\\n ? transferNativeAsset(recipient, amount)\\n : transferERC20(assetId, recipient, amount);\\n }\\n\\n /// @dev Checks whether the given address is a contract and contains code\\n function isContract(address _contractAddr) internal view returns (bool) {\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n size := extcodesize(_contractAddr)\\n }\\n return size > 0;\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibSwap.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { LibAsset } from \\\"./LibAsset.sol\\\";\\nimport { LibUtil } from \\\"./LibUtil.sol\\\";\\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LibSwap {\\n struct SwapData {\\n address callTo;\\n address approveTo;\\n address sendingAssetId;\\n address receivingAssetId;\\n uint256 fromAmount;\\n bytes callData;\\n bool requiresDeposit;\\n }\\n\\n event AssetSwapped(\\n bytes32 transactionId,\\n address dex,\\n address fromAssetId,\\n address toAssetId,\\n uint256 fromAmount,\\n uint256 toAmount,\\n uint256 timestamp\\n );\\n\\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\\n uint256 fromAmount = _swap.fromAmount;\\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\\n ? _swap.fromAmount\\n : 0;\\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\\n _swap.sendingAssetId\\n );\\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\\n _swap.receivingAssetId\\n );\\n\\n if (nativeValue == 0) {\\n LibAsset.maxApproveERC20(\\n IERC20(_swap.sendingAssetId),\\n _swap.approveTo,\\n _swap.fromAmount\\n );\\n }\\n\\n if (initialSendingAssetBalance < _swap.fromAmount) {\\n revert InsufficientBalance(\\n _swap.fromAmount,\\n initialSendingAssetBalance\\n );\\n }\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory res) = _swap.callTo.call{\\n value: nativeValue\\n }(_swap.callData);\\n if (!success) {\\n LibUtil.revertWith(res);\\n }\\n\\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\\n\\n emit AssetSwapped(\\n transactionId,\\n _swap.callTo,\\n _swap.sendingAssetId,\\n _swap.receivingAssetId,\\n _swap.fromAmount,\\n newBalance > initialReceivingAssetBalance\\n ? newBalance - initialReceivingAssetBalance\\n : newBalance,\\n block.timestamp\\n );\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/ReentrancyGuard.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\n/// @title Reentrancy Guard\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide protection against reentrancy\\nabstract contract ReentrancyGuard {\\n /// Storage ///\\n\\n bytes32 private constant NAMESPACE = keccak256(\\\"com.lifi.reentrancyguard\\\");\\n\\n /// Types ///\\n\\n struct ReentrancyStorage {\\n uint256 status;\\n }\\n\\n /// Errors ///\\n\\n error ReentrancyError();\\n\\n /// Constants ///\\n\\n uint256 private constant _NOT_ENTERED = 0;\\n uint256 private constant _ENTERED = 1;\\n\\n /// Modifiers ///\\n\\n modifier nonReentrant() {\\n ReentrancyStorage storage s = reentrancyStorage();\\n if (s.status == _ENTERED) revert ReentrancyError();\\n s.status = _ENTERED;\\n _;\\n s.status = _NOT_ENTERED;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev fetch local storage\\n function reentrancyStorage()\\n private\\n pure\\n returns (ReentrancyStorage storage data)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n data.slot := position\\n }\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/SwapperV2.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibAllowList } from \\\"../Libraries/LibAllowList.sol\\\";\\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Swapper\\n/// @author LI.FI (https://li.fi)\\n/// @notice Abstract contract to provide swap functionality\\ncontract SwapperV2 is ILiFi {\\n /// Types ///\\n\\n /// @dev only used to get around \\\"Stack Too Deep\\\" errors\\n struct ReserveData {\\n bytes32 transactionId;\\n address payable leftoverReceiver;\\n uint256 nativeReserve;\\n }\\n\\n /// Modifiers ///\\n\\n /// @dev Sends any leftover balances back to the user\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftovers(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Sends any leftover balances back to the user reserving native tokens\\n /// @notice Sends any leftover balances to the user\\n /// @param _swaps Swap data array\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial token balances\\n modifier noLeftoversReserve(\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances,\\n uint256 _nativeReserve\\n ) {\\n uint256 numSwaps = _swaps.length;\\n if (numSwaps != 1) {\\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 curBalance;\\n\\n _;\\n\\n for (uint256 i = 0; i < numSwaps - 1; ) {\\n address curAsset = _swaps[i].receivingAssetId;\\n // Handle multi-to-one swaps\\n if (curAsset != finalAsset) {\\n curBalance =\\n LibAsset.getOwnBalance(curAsset) -\\n _initialBalances[i];\\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\\n ? _nativeReserve\\n : 0;\\n if (curBalance > 0) {\\n LibAsset.transferAsset(\\n curAsset,\\n _leftoverReceiver,\\n curBalance - reserve\\n );\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n } else {\\n _;\\n }\\n }\\n\\n /// @dev Refunds any excess native asset sent to the contract after the main function\\n /// @notice Refunds any excess native asset sent to the contract after the main function\\n /// @param _refundReceiver Address to send refunds to\\n modifier refundExcessNative(address payable _refundReceiver) {\\n uint256 initialBalance = address(this).balance - msg.value;\\n _;\\n uint256 finalBalance = address(this).balance;\\n\\n if (finalBalance > initialBalance) {\\n LibAsset.transferAsset(\\n LibAsset.NATIVE_ASSETID,\\n _refundReceiver,\\n finalBalance - initialBalance\\n );\\n }\\n }\\n\\n /// Internal Methods ///\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @return uint256 result of the swap\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n _executeSwaps(\\n _transactionId,\\n _swaps,\\n _leftoverReceiver,\\n initialBalances\\n );\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _minAmount the minimum amount of the final asset to receive\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver The address to send leftover funds to\\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\\n function _depositAndSwap(\\n bytes32 _transactionId,\\n uint256 _minAmount,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256 _nativeReserve\\n ) internal returns (uint256) {\\n uint256 numSwaps = _swaps.length;\\n\\n if (numSwaps == 0) {\\n revert NoSwapDataProvided();\\n }\\n\\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n initialBalance -= msg.value;\\n }\\n\\n uint256[] memory initialBalances = _fetchBalances(_swaps);\\n\\n LibAsset.depositAssets(_swaps);\\n ReserveData memory rd = ReserveData(\\n _transactionId,\\n _leftoverReceiver,\\n _nativeReserve\\n );\\n _executeSwaps(rd, _swaps, initialBalances);\\n\\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\\n initialBalance;\\n\\n if (LibAsset.isNativeAsset(finalTokenId)) {\\n newBalance -= _nativeReserve;\\n }\\n\\n if (newBalance < _minAmount) {\\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\\n }\\n\\n return newBalance;\\n }\\n\\n /// Private Methods ///\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _transactionId the transaction id associated with the operation\\n /// @param _swaps Array of data used to execute swaps\\n /// @param _leftoverReceiver Address to send leftover tokens to\\n /// @param _initialBalances Array of initial balances\\n function _executeSwaps(\\n bytes32 _transactionId,\\n LibSwap.SwapData[] calldata _swaps,\\n address payable _leftoverReceiver,\\n uint256[] memory _initialBalances\\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Executes swaps and checks that DEXs used are in the allowList\\n /// @param _reserveData Data passed used to reserve native tokens\\n /// @param _swaps Array of data used to execute swaps\\n function _executeSwaps(\\n ReserveData memory _reserveData,\\n LibSwap.SwapData[] calldata _swaps,\\n uint256[] memory _initialBalances\\n )\\n internal\\n noLeftoversReserve(\\n _swaps,\\n _reserveData.leftoverReceiver,\\n _initialBalances,\\n _reserveData.nativeReserve\\n )\\n {\\n uint256 numSwaps = _swaps.length;\\n for (uint256 i = 0; i < numSwaps; ) {\\n LibSwap.SwapData calldata currentSwap = _swaps[i];\\n\\n if (\\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\\n LibAllowList.selectorIsAllowed(\\n bytes4(currentSwap.callData[:4])\\n ))\\n ) revert ContractCallNotAllowed();\\n\\n LibSwap.swap(_reserveData.transactionId, currentSwap);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /// @dev Fetches balances of tokens to be swapped before swapping.\\n /// @param _swaps Array of data used to execute swaps\\n /// @return uint256[] Array of token balances.\\n function _fetchBalances(\\n LibSwap.SwapData[] calldata _swaps\\n ) private view returns (uint256[] memory) {\\n uint256 numSwaps = _swaps.length;\\n uint256[] memory balances = new uint256[](numSwaps);\\n address asset;\\n for (uint256 i = 0; i < numSwaps; ) {\\n asset = _swaps[i].receivingAssetId;\\n balances[i] = LibAsset.getOwnBalance(asset);\\n\\n if (LibAsset.isNativeAsset(asset)) {\\n balances[i] -= msg.value;\\n }\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return balances;\\n }\\n}\\n\"\r\n },\r\n \"src/Helpers/Validatable.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: UNLICENSED\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { LibAsset } from \\\"../Libraries/LibAsset.sol\\\";\\nimport { LibUtil } from \\\"../Libraries/LibUtil.sol\\\";\\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \\\"../Errors/GenericErrors.sol\\\";\\nimport { ILiFi } from \\\"../Interfaces/ILiFi.sol\\\";\\nimport { LibSwap } from \\\"../Libraries/LibSwap.sol\\\";\\n\\ncontract Validatable {\\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\\n revert InvalidReceiver();\\n }\\n if (_bridgeData.minAmount == 0) {\\n revert InvalidAmount();\\n }\\n if (_bridgeData.destinationChainId == block.chainid) {\\n revert CannotBridgeToSameNetwork();\\n }\\n _;\\n }\\n\\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\\n revert NativeAssetNotSupported();\\n }\\n _;\\n }\\n\\n modifier onlyAllowSourceToken(\\n ILiFi.BridgeData memory _bridgeData,\\n address _token\\n ) {\\n if (_bridgeData.sendingAssetId != _token) {\\n revert InvalidSendingToken();\\n }\\n _;\\n }\\n\\n modifier onlyAllowDestinationChain(\\n ILiFi.BridgeData memory _bridgeData,\\n uint256 _chainId\\n ) {\\n if (_bridgeData.destinationChainId != _chainId) {\\n revert InvalidDestinationChain();\\n }\\n _;\\n }\\n\\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (!_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\\n if (_bridgeData.hasSourceSwaps) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n\\n modifier doesNotContainDestinationCalls(\\n ILiFi.BridgeData memory _bridgeData\\n ) {\\n if (_bridgeData.hasDestinationCall) {\\n revert InformationMismatch();\\n }\\n _;\\n }\\n}\\n\"\r\n },\r\n \"src/Interfaces/IDlnSource.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\ninterface IDlnSource {\\n struct OrderCreation {\\n // the address of the ERC-20 token you are giving;\\n // use the zero address to indicate you are giving a native blockchain token (ether, matic, etc).\\n address giveTokenAddress;\\n // the amount of tokens you are giving\\n uint256 giveAmount;\\n // the address of the ERC-20 token you are willing to take on the destination chain\\n bytes takeTokenAddress;\\n // the amount of tokens you are willing to take on the destination chain\\n uint256 takeAmount;\\n // the ID of the chain where an order should be fulfilled.\\n // Use the list of supported chains mentioned above\\n uint256 takeChainId;\\n // the address on the destination chain where the funds\\n // should be sent to upon order fulfillment\\n bytes receiverDst;\\n // the address on the source (current) chain who is allowed to patch the order\\n // giving more input tokens and thus making the order more attractive to takers, just in case\\n address givePatchAuthoritySrc;\\n // the address on the destination chain who is allowed to patch the order\\n // decreasing the take amount and thus making the order more attractive to takers, just in case\\n bytes orderAuthorityAddressDst;\\n // an optional address restricting anyone in the open market from fulfilling\\n // this order but the given address. This can be useful if you are creating a order\\n // for a specific taker. By default, set to empty bytes array (0x)\\n bytes allowedTakerDst; // *optional\\n // set to an empty bytes array (0x)\\n bytes externalCall; // N/A, *optional\\n // an optional address on the source (current) chain where the given input tokens\\n // would be transferred to in case order cancellation is initiated by the orderAuthorityAddressDst\\n // on the destination chain. This property can be safely set to an empty bytes array (0x):\\n // in this case, tokens would be transferred to the arbitrary address specified\\n // by the orderAuthorityAddressDst upon order cancellation\\n bytes allowedCancelBeneficiarySrc; // *optional\\n }\\n\\n function globalFixedNativeFee() external returns (uint256);\\n\\n function createOrder(\\n OrderCreation calldata _orderCreation,\\n bytes calldata _affiliateFee,\\n uint32 _referralCode,\\n bytes calldata _permitEnvelope\\n ) external payable returns (bytes32 orderId);\\n}\\n\"\r\n },\r\n \"src/Errors/GenericErrors.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nerror AlreadyInitialized();\\nerror CannotAuthoriseSelf();\\nerror CannotBridgeToSameNetwork();\\nerror ContractCallNotAllowed();\\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\\nerror DiamondIsPaused();\\nerror ExternalCallFailed();\\nerror FunctionDoesNotExist();\\nerror InformationMismatch();\\nerror InsufficientBalance(uint256 required, uint256 balance);\\nerror InvalidAmount();\\nerror InvalidCallData();\\nerror InvalidConfig();\\nerror InvalidContract();\\nerror InvalidDestinationChain();\\nerror InvalidFallbackAddress();\\nerror InvalidReceiver();\\nerror InvalidSendingToken();\\nerror NativeAssetNotSupported();\\nerror NativeAssetTransferFailed();\\nerror NoSwapDataProvided();\\nerror NoSwapFromZeroBalance();\\nerror NotAContract();\\nerror NotInitialized();\\nerror NoTransferToNullAddress();\\nerror NullAddrIsNotAnERC20Token();\\nerror NullAddrIsNotAValidSpender();\\nerror OnlyContractOwner();\\nerror RecoveryAddressCannotBeZero();\\nerror ReentrancyError();\\nerror TokenNotSupported();\\nerror UnAuthorized();\\nerror UnsupportedChainId(uint256 chainId);\\nerror WithdrawFailed();\\nerror ZeroAmount();\\n\"\r\n },\r\n \"src/Libraries/LibUtil.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport \\\"./LibBytes.sol\\\";\\n\\nlibrary LibUtil {\\n using LibBytes for bytes;\\n\\n function getRevertMsg(\\n bytes memory _res\\n ) internal pure returns (string memory) {\\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\\n if (_res.length < 68) return \\\"Transaction reverted silently\\\";\\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\\n return abi.decode(revertData, (string)); // All that remains is the revert string\\n }\\n\\n /// @notice Determines whether the given address is the zero address\\n /// @param addr The address to verify\\n /// @return Boolean indicating if the address is the zero address\\n function isZeroAddress(address addr) internal pure returns (bool) {\\n return addr == address(0);\\n }\\n\\n function revertWith(bytes memory data) internal pure {\\n assembly {\\n let dataSize := mload(data) // Load the size of the data\\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\\n revert(dataPtr, dataSize) // Revert with the given data\\n }\\n }\\n}\\n\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\\n * 0 before setting it to a non-zero value.\\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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol\": {\r\n \"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\"\r\n },\r\n \"src/Libraries/LibAllowList.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nimport { InvalidContract } from \\\"../Errors/GenericErrors.sol\\\";\\n\\n/// @title Lib Allow List\\n/// @author LI.FI (https://li.fi)\\n/// @notice Library for managing and accessing the conract address allow list\\nlibrary LibAllowList {\\n /// Storage ///\\n bytes32 internal constant NAMESPACE =\\n keccak256(\\\"com.lifi.library.allow.list\\\");\\n\\n struct AllowListStorage {\\n mapping(address => bool) allowlist;\\n mapping(bytes4 => bool) selectorAllowList;\\n address[] contracts;\\n }\\n\\n /// @dev Adds a contract address to the allow list\\n /// @param _contract the contract address to add\\n function addAllowedContract(address _contract) internal {\\n _checkAddress(_contract);\\n\\n AllowListStorage storage als = _getStorage();\\n\\n if (als.allowlist[_contract]) return;\\n\\n als.allowlist[_contract] = true;\\n als.contracts.push(_contract);\\n }\\n\\n /// @dev Checks whether a contract address has been added to the allow list\\n /// @param _contract the contract address to check\\n function contractIsAllowed(\\n address _contract\\n ) internal view returns (bool) {\\n return _getStorage().allowlist[_contract];\\n }\\n\\n /// @dev Remove a contract address from the allow list\\n /// @param _contract the contract address to remove\\n function removeAllowedContract(address _contract) internal {\\n AllowListStorage storage als = _getStorage();\\n\\n if (!als.allowlist[_contract]) {\\n return;\\n }\\n\\n als.allowlist[_contract] = false;\\n\\n uint256 length = als.contracts.length;\\n // Find the contract in the list\\n for (uint256 i = 0; i < length; i++) {\\n if (als.contracts[i] == _contract) {\\n // Move the last element into the place to delete\\n als.contracts[i] = als.contracts[length - 1];\\n // Remove the last element\\n als.contracts.pop();\\n break;\\n }\\n }\\n }\\n\\n /// @dev Fetch contract addresses from the allow list\\n function getAllowedContracts() internal view returns (address[] memory) {\\n return _getStorage().contracts;\\n }\\n\\n /// @dev Add a selector to the allow list\\n /// @param _selector the selector to add\\n function addAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = true;\\n }\\n\\n /// @dev Removes a selector from the allow list\\n /// @param _selector the selector to remove\\n function removeAllowedSelector(bytes4 _selector) internal {\\n _getStorage().selectorAllowList[_selector] = false;\\n }\\n\\n /// @dev Returns if selector has been added to the allow list\\n /// @param _selector the selector to check\\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\\n return _getStorage().selectorAllowList[_selector];\\n }\\n\\n /// @dev Fetch local storage struct\\n function _getStorage()\\n internal\\n pure\\n returns (AllowListStorage storage als)\\n {\\n bytes32 position = NAMESPACE;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n als.slot := position\\n }\\n }\\n\\n /// @dev Contains business logic for validating a contract address.\\n /// @param _contract address of the dex to check\\n function _checkAddress(address _contract) private view {\\n if (_contract == address(0)) revert InvalidContract();\\n\\n if (_contract.code.length == 0) revert InvalidContract();\\n }\\n}\\n\"\r\n },\r\n \"src/Libraries/LibBytes.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n/// @custom:version 1.0.0\\npragma solidity ^0.8.17;\\n\\nlibrary LibBytes {\\n // solhint-disable no-inline-assembly\\n\\n // LibBytes specific errors\\n error SliceOverflow();\\n error SliceOutOfBounds();\\n error AddressOutOfBounds();\\n\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n // -------------------------\\n\\n function slice(\\n bytes memory _bytes,\\n uint256 _start,\\n uint256 _length\\n ) internal pure returns (bytes memory) {\\n if (_length + 31 < _length) revert SliceOverflow();\\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\\n\\n bytes memory tempBytes;\\n\\n assembly {\\n switch iszero(_length)\\n case 0 {\\n // Get a location of some free memory and store it in tempBytes as\\n // Solidity does for memory variables.\\n tempBytes := mload(0x40)\\n\\n // The first word of the slice result is potentially a partial\\n // word read from the original array. To read it, we calculate\\n // the length of that partial word and start copying that many\\n // bytes into the array. The first word we copy will start with\\n // data we don't care about, but the last `lengthmod` bytes will\\n // land at the beginning of the contents of the new array. When\\n // we're done copying, we overwrite the full first word with\\n // the actual length of the slice.\\n let lengthmod := and(_length, 31)\\n\\n // The multiplication in the next line is necessary\\n // because when slicing multiples of 32 bytes (lengthmod == 0)\\n // the following copy loop was copying the origin's length\\n // and then ending prematurely not copying everything it should.\\n let mc := add(\\n add(tempBytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n )\\n let end := add(mc, _length)\\n\\n for {\\n // The multiplication in the next line has the same exact purpose\\n // as the one above.\\n let cc := add(\\n add(\\n add(_bytes, lengthmod),\\n mul(0x20, iszero(lengthmod))\\n ),\\n _start\\n )\\n } lt(mc, end) {\\n mc := add(mc, 0x20)\\n cc := add(cc, 0x20)\\n } {\\n mstore(mc, mload(cc))\\n }\\n\\n mstore(tempBytes, _length)\\n\\n //update free-memory pointer\\n //allocating the array padded to 32 bytes like the compiler does now\\n mstore(0x40, and(add(mc, 31), not(31)))\\n }\\n //if we want a zero-length slice let's just return a zero-length array\\n default {\\n tempBytes := mload(0x40)\\n //zero out the 32 bytes slice we are about to return\\n //we need to do it because Solidity does not garbage collect\\n mstore(tempBytes, 0)\\n\\n mstore(0x40, add(tempBytes, 0x20))\\n }\\n }\\n\\n return tempBytes;\\n }\\n\\n function toAddress(\\n bytes memory _bytes,\\n uint256 _start\\n ) internal pure returns (address) {\\n if (_bytes.length < _start + 20) {\\n revert AddressOutOfBounds();\\n }\\n address tempAddress;\\n\\n assembly {\\n tempAddress := div(\\n mload(add(add(_bytes, 0x20), _start)),\\n 0x1000000000000000000000000\\n )\\n }\\n\\n return tempAddress;\\n }\\n\\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\\n function toHexString(\\n uint256 value,\\n uint256 length\\n ) 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol\": {\r\n \"content\": \"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\\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 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\"\r\n },\r\n \"lib/openzeppelin-contracts/contracts/utils/Address.sol\": {\r\n \"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\"\r\n }\r\n },\r\n \"settings\": {\r\n \"remappings\": [\r\n \"@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/\",\r\n \"@uniswap/=node_modules/@uniswap/\",\r\n \"eth-gas-reporter/=node_modules/eth-gas-reporter/\",\r\n \"hardhat/=node_modules/hardhat/\",\r\n \"hardhat-deploy/=node_modules/hardhat-deploy/\",\r\n \"@openzeppelin/=lib/openzeppelin-contracts/\",\r\n \"celer-network/=lib/sgn-v2-contracts/\",\r\n \"create3-factory/=lib/create3-factory/src/\",\r\n \"solmate/=lib/solmate/src/\",\r\n \"solady/=lib/solady/src/\",\r\n \"permit2/=lib/Permit2/src/\",\r\n \"ds-test/=lib/ds-test/src/\",\r\n \"forge-std/=lib/forge-std/src/\",\r\n \"lifi/=src/\",\r\n \"test/=test/\",\r\n \"Permit2/=lib/Permit2/\",\r\n \"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\r\n \"forge-gas-snapshot/=lib/Permit2/lib/forge-gas-snapshot/src/\",\r\n \"openzeppelin-contracts/=lib/openzeppelin-contracts/\",\r\n \"openzeppelin/=lib/openzeppelin-contracts/contracts/\",\r\n \"sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/\"\r\n ],\r\n \"optimizer\": {\r\n \"enabled\": true,\r\n \"runs\": 1000000\r\n },\r\n \"metadata\": {\r\n \"useLiteralContent\": false,\r\n \"bytecodeHash\": \"ipfs\"\r\n },\r\n \"outputSelection\": {\r\n \"*\": {\r\n \"*\": [\r\n \"evm.bytecode\",\r\n \"evm.deployedBytecode\",\r\n \"devdoc\",\r\n \"userdoc\",\r\n \"metadata\",\r\n \"abi\"\r\n ]\r\n }\r\n },\r\n \"evmVersion\": \"london\",\r\n \"viaIR\": false,\r\n \"libraries\": {}\r\n }\r\n}}", + ABI: "[{\"inputs\":[{\"internalType\":\"contract IDlnSource\",\"name\":\"_dlnSource\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotBridgeToSameNetwork\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ContractCallNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"receivedAmount\",\"type\":\"uint256\"}],\"name\":\"CumulativeSlippageTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyNonEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InformationMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReceiver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NativeAssetTransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapDataProvided\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoSwapFromZeroBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoTransferToNullAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotInitialized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAValidSpender\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NullAddrIsNotAnERC20Token\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyContractOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnknownDeBridgeChain\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"}],\"name\":\"BridgeToNonEVMChain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"deBridgeChainId\",\"type\":\"uint256\"}],\"name\":\"DeBridgeChainIdSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deBridgeChainId\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"struct DeBridgeDlnFacet.ChainIdConfig[]\",\"name\":\"chainIdConfigs\",\"type\":\"tuple[]\"}],\"name\":\"DeBridgeInitialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"orderId\",\"type\":\"bytes32\"}],\"name\":\"DlnOrderCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiGenericSwapCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"referrer\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"fromAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"toAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"toAmount\",\"type\":\"uint256\"}],\"name\":\"LiFiSwappedGeneric\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"LiFiTransferRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"bridgeData\",\"type\":\"tuple\"}],\"name\":\"LiFiTransferStarted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"dlnSource\",\"outputs\":[{\"internalType\":\"contract IDlnSource\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_chainId\",\"type\":\"uint256\"}],\"name\":\"getDeBridgeChainId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deBridgeChainId\",\"type\":\"uint256\"}],\"internalType\":\"struct DeBridgeDlnFacet.ChainIdConfig[]\",\"name\":\"chainIdConfigs\",\"type\":\"tuple[]\"}],\"name\":\"initDeBridgeDln\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_chainId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_deBridgeChainId\",\"type\":\"uint256\"}],\"name\":\"setDeBridgeChainId\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receivingAssetId\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"orderAuthorityDst\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"minAmountOut\",\"type\":\"uint256\"}],\"internalType\":\"struct DeBridgeDlnFacet.DeBridgeDlnData\",\"name\":\"_deBridgeData\",\"type\":\"tuple\"}],\"name\":\"startBridgeTokensViaDeBridgeDln\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"transactionId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"bridge\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"integrator\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"referrer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"destinationChainId\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"hasSourceSwaps\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"hasDestinationCall\",\"type\":\"bool\"}],\"internalType\":\"struct ILiFi.BridgeData\",\"name\":\"_bridgeData\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"callTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"approveTo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sendingAssetId\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"receivingAssetId\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"requiresDeposit\",\"type\":\"bool\"}],\"internalType\":\"struct LibSwap.SwapData[]\",\"name\":\"_swapData\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receivingAssetId\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"orderAuthorityDst\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"minAmountOut\",\"type\":\"uint256\"}],\"internalType\":\"struct DeBridgeDlnFacet.DeBridgeDlnData\",\"name\":\"_deBridgeData\",\"type\":\"tuple\"}],\"name\":\"swapAndStartBridgeTokensViaDeBridgeDln\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"}]", + ContractName: "DeBridgeDlnFacet", + CompilerVersion: "v0.8.17+commit.8df45f5f", + OptimizationUsed: "1", + Runs: "1000000", + ConstructorArguments: "000000000000000000000000ef4fb24ad0916217251f553c0596f8edc630eb66", + EVMVersion: "london", + Library: "", + LicenseType: "", + Proxy: "0", + Implementation: "", + SwarmSource: "", + SimilarMatch: "", +} +{{ + "language": "Solidity", + "sources": { + "src/Facets/DeBridgeDlnFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { LibAsset, IERC20 } from \"../Libraries/LibAsset.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { ReentrancyGuard } from \"../Helpers/ReentrancyGuard.sol\";\nimport { SwapperV2 } from \"../Helpers/SwapperV2.sol\";\nimport { Validatable } from \"../Helpers/Validatable.sol\";\nimport { IDlnSource } from \"../Interfaces/IDlnSource.sol\";\nimport { NotInitialized } from \"../Errors/GenericErrors.sol\";\n\n/// @title DeBridgeDLN Facet\n/// @author LI.FI (https://li.fi)\n/// @notice Provides functionality for bridging through DeBridge DLN\n/// @custom:version 1.0.0\ncontract DeBridgeDlnFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {\n /// Storage ///\n\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.facets.debridgedln\");\n uint32 internal constant REFERRAL_CODE = 30729;\n address internal constant NON_EVM_ADDRESS =\n 0x11f111f111f111F111f111f111F111f111f111F1;\n IDlnSource public immutable dlnSource;\n\n /// Types ///\n\n /// @param receivingAssetId The address of the asset to receive\n /// @param receiver The address of the receiver\n /// @param minAmountOut The minimum amount to receive on the destination chain\n struct DeBridgeDlnData {\n bytes receivingAssetId;\n bytes receiver;\n bytes orderAuthorityDst;\n uint256 minAmountOut;\n }\n\n struct Storage {\n mapping(uint256 => uint256) deBridgeChainId;\n bool initialized;\n }\n\n struct ChainIdConfig {\n uint256 chainId;\n uint256 deBridgeChainId;\n }\n\n /// Errors ///\n\n error UnknownDeBridgeChain();\n error EmptyNonEVMAddress();\n error InvalidConfig();\n\n /// Events ///\n\n event DeBridgeInitialized(ChainIdConfig[] chainIdConfigs);\n\n event DlnOrderCreated(bytes32 indexed orderId);\n\n event DeBridgeChainIdSet(uint256 indexed chainId, uint256 deBridgeChainId);\n\n event BridgeToNonEVMChain(\n bytes32 indexed transactionId,\n uint256 indexed destinationChainId,\n bytes receiver\n );\n\n /// Modifiers ///\n\n modifier onlyValidReceiverAddress(DeBridgeDlnData calldata _deBridgeData) {\n // Ensure nonEVMAddress is not empty\n if (_deBridgeData.receiver.length == 0) {\n revert EmptyNonEVMAddress();\n }\n _;\n }\n\n /// Constructor ///\n\n /// @notice Constructor for the contract.\n /// @param _dlnSource The address of the DLN order creation contract\n constructor(IDlnSource _dlnSource) {\n dlnSource = _dlnSource;\n }\n\n /// Init ///\n\n /// @notice Initialize local variables for the DeBridgeDln Facet\n /// @param chainIdConfigs Chain Id configuration data\n function initDeBridgeDln(\n ChainIdConfig[] calldata chainIdConfigs\n ) external {\n if (chainIdConfigs.length == 0) revert InvalidConfig();\n LibDiamond.enforceIsContractOwner();\n\n Storage storage sm = getStorage();\n\n for (uint256 i = 0; i < chainIdConfigs.length; i++) {\n sm.deBridgeChainId[chainIdConfigs[i].chainId] = chainIdConfigs[i]\n .deBridgeChainId;\n }\n\n sm.initialized = true;\n emit DeBridgeInitialized(chainIdConfigs);\n }\n\n /// External Methods ///\n\n /// @notice Bridges tokens via DeBridgeDLN\n /// @param _bridgeData The core information needed for bridging\n /// @param _deBridgeData Data specific to DeBridgeDLN\n function startBridgeTokensViaDeBridgeDln(\n ILiFi.BridgeData memory _bridgeData,\n DeBridgeDlnData calldata _deBridgeData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n validateBridgeData(_bridgeData)\n onlyValidReceiverAddress(_deBridgeData)\n doesNotContainSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n {\n LibAsset.depositAsset(\n _bridgeData.sendingAssetId,\n _bridgeData.minAmount\n );\n _startBridge(\n _bridgeData,\n _deBridgeData,\n dlnSource.globalFixedNativeFee()\n );\n }\n\n /// @notice Performs a swap before bridging via DeBridgeDLN\n /// @param _bridgeData The core information needed for bridging\n /// @param _swapData An array of swap related data for performing swaps before bridging\n /// @param _deBridgeData Data specific to DeBridgeDLN\n function swapAndStartBridgeTokensViaDeBridgeDln(\n ILiFi.BridgeData memory _bridgeData,\n LibSwap.SwapData[] calldata _swapData,\n DeBridgeDlnData calldata _deBridgeData\n )\n external\n payable\n nonReentrant\n refundExcessNative(payable(msg.sender))\n containsSourceSwaps(_bridgeData)\n doesNotContainDestinationCalls(_bridgeData)\n validateBridgeData(_bridgeData)\n onlyValidReceiverAddress(_deBridgeData)\n {\n uint256 fee = dlnSource.globalFixedNativeFee();\n address assetId = _bridgeData.sendingAssetId;\n _bridgeData.minAmount = _depositAndSwap(\n _bridgeData.transactionId,\n _bridgeData.minAmount,\n _swapData,\n payable(msg.sender),\n LibAsset.isNativeAsset(assetId) ? 0 : fee\n );\n _startBridge(_bridgeData, _deBridgeData, fee);\n }\n\n /// Internal Methods ///\n\n /// @dev Contains the business logic for the bridge via DeBridgeDLN\n /// @param _bridgeData The core information needed for bridging\n /// @param _deBridgeData Data specific to DeBridgeDLN\n function _startBridge(\n ILiFi.BridgeData memory _bridgeData,\n DeBridgeDlnData calldata _deBridgeData,\n uint256 _fee\n ) internal {\n IDlnSource.OrderCreation memory orderCreation = IDlnSource\n .OrderCreation({\n giveTokenAddress: _bridgeData.sendingAssetId,\n giveAmount: _bridgeData.minAmount,\n takeTokenAddress: _deBridgeData.receivingAssetId,\n takeAmount: _deBridgeData.minAmountOut,\n takeChainId: getDeBridgeChainId(\n _bridgeData.destinationChainId\n ),\n receiverDst: _deBridgeData.receiver,\n givePatchAuthoritySrc: msg.sender,\n orderAuthorityAddressDst: _deBridgeData.orderAuthorityDst,\n allowedTakerDst: \"\",\n externalCall: \"\",\n allowedCancelBeneficiarySrc: abi.encodePacked(msg.sender)\n });\n\n bytes32 orderId;\n if (!LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n // Give the DLN Source approval to bridge tokens\n LibAsset.maxApproveERC20(\n IERC20(_bridgeData.sendingAssetId),\n address(dlnSource),\n _bridgeData.minAmount\n );\n\n orderId = dlnSource.createOrder{ value: _fee }(\n orderCreation,\n \"\",\n REFERRAL_CODE,\n \"\"\n );\n } else {\n orderCreation.giveAmount = orderCreation.giveAmount - _fee;\n orderId = dlnSource.createOrder{ value: _bridgeData.minAmount }(\n orderCreation,\n \"\",\n REFERRAL_CODE,\n \"\"\n );\n }\n\n emit DlnOrderCreated(orderId);\n\n if (_bridgeData.receiver == NON_EVM_ADDRESS) {\n emit BridgeToNonEVMChain(\n _bridgeData.transactionId,\n _bridgeData.destinationChainId,\n _deBridgeData.receiver\n );\n }\n\n emit LiFiTransferStarted(_bridgeData);\n }\n\n /// Mappings management ///\n\n /// @notice Sets the DeBridge chain ID for a given chain ID\n /// @param _chainId uint256 of the chain ID\n /// @param _deBridgeChainId uint256 of the DeBridge chain ID\n /// @dev This is used to map a chain ID to its DeBridge chain ID\n function setDeBridgeChainId(\n uint256 _chainId,\n uint256 _deBridgeChainId\n ) external {\n LibDiamond.enforceIsContractOwner();\n Storage storage sm = getStorage();\n\n if (!sm.initialized) {\n revert NotInitialized();\n }\n\n sm.deBridgeChainId[_chainId] = _deBridgeChainId;\n emit DeBridgeChainIdSet(_chainId, _deBridgeChainId);\n }\n\n /// @notice Gets the DeBridge chain ID for a given chain ID\n /// @param _chainId uint256 of the chain ID\n /// @return uint256 of the DeBridge chain ID\n function getDeBridgeChainId(\n uint256 _chainId\n ) public view returns (uint256) {\n Storage storage sm = getStorage();\n uint256 chainId = sm.deBridgeChainId[_chainId];\n if (chainId == 0) revert UnknownDeBridgeChain();\n return chainId;\n }\n\n /// @dev fetch local storage\n function getStorage() private pure returns (Storage storage s) {\n bytes32 namespace = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n s.slot := namespace\n }\n }\n}\n" + }, + "src/Interfaces/ILiFi.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\ninterface ILiFi {\n /// Structs ///\n\n struct BridgeData {\n bytes32 transactionId;\n string bridge;\n string integrator;\n address referrer;\n address sendingAssetId;\n address receiver;\n uint256 minAmount;\n uint256 destinationChainId;\n bool hasSourceSwaps;\n bool hasDestinationCall;\n }\n\n /// Events ///\n\n event LiFiTransferStarted(ILiFi.BridgeData bridgeData);\n\n event LiFiTransferCompleted(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiTransferRecovered(\n bytes32 indexed transactionId,\n address receivingAssetId,\n address receiver,\n uint256 amount,\n uint256 timestamp\n );\n\n event LiFiGenericSwapCompleted(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address receiver,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n\n // Deprecated but kept here to include in ABI to parse historic events\n event LiFiSwappedGeneric(\n bytes32 indexed transactionId,\n string integrator,\n string referrer,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount\n );\n}\n" + }, + "src/Libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.17;\n\n// import { IDiamondCut } from \"../Interfaces/LibDiamond.sol\";\nimport { LibDiamond } from \"../Libraries/LibDiamond.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { OnlyContractOwner } from \"../Errors/GenericErrors.sol\";\n\n/// Implementation of EIP-2535 Diamond Standard\n/// https://eips.ethereum.org/EIPS/eip-2535\nlibrary LibDiamond {\n bytes32 internal constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n // Diamond specific errors\n error IncorrectFacetCutAction();\n error NoSelectorsInFace();\n error FunctionAlreadyExists();\n error FacetAddressIsZero();\n error FacetAddressIsNotZero();\n error FacetContainsNoCode();\n error FunctionDoesNotExist();\n error FunctionIsImmutable();\n error InitZeroButCalldataNotEmpty();\n error CalldataEmptyButInitNotZero();\n error InitReverted();\n // ----------------\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n if (msg.sender != diamondStorage().contractOwner)\n revert OnlyContractOwner();\n }\n\n // Internal function version of diamondCut\n function diamondCut(\n FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; ) {\n LibDiamond.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == LibDiamond.FacetCutAction.Add) {\n addFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == LibDiamond.FacetCutAction.Replace) {\n replaceFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else if (action == LibDiamond.FacetCutAction.Remove) {\n removeFunctions(\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].functionSelectors\n );\n } else {\n revert IncorrectFacetCutAction();\n }\n unchecked {\n ++facetIndex;\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (!LibUtil.isZeroAddress(oldFacetAddress)) {\n revert FunctionAlreadyExists();\n }\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function replaceFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsZero();\n }\n uint96 selectorPosition = uint96(\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.length\n );\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n if (oldFacetAddress == _facetAddress) {\n revert FunctionAlreadyExists();\n }\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n unchecked {\n ++selectorPosition;\n ++selectorIndex;\n }\n }\n }\n\n function removeFunctions(\n address _facetAddress,\n bytes4[] memory _functionSelectors\n ) internal {\n if (_functionSelectors.length == 0) {\n revert NoSelectorsInFace();\n }\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n if (!LibUtil.isZeroAddress(_facetAddress)) {\n revert FacetAddressIsNotZero();\n }\n for (\n uint256 selectorIndex;\n selectorIndex < _functionSelectors.length;\n\n ) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds\n .selectorToFacetAndPosition[selector]\n .facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n unchecked {\n ++selectorIndex;\n }\n }\n }\n\n function addFacet(\n DiamondStorage storage ds,\n address _facetAddress\n ) internal {\n enforceHasContractCode(_facetAddress);\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds\n .facetAddresses\n .length;\n ds.facetAddresses.push(_facetAddress);\n }\n\n function addFunction(\n DiamondStorage storage ds,\n bytes4 _selector,\n uint96 _selectorPosition,\n address _facetAddress\n ) internal {\n ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(\n _selector\n );\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(\n DiamondStorage storage ds,\n address _facetAddress,\n bytes4 _selector\n ) internal {\n if (LibUtil.isZeroAddress(_facetAddress)) {\n revert FunctionDoesNotExist();\n }\n // an immutable function is a function defined directly in a diamond\n if (_facetAddress == address(this)) {\n revert FunctionIsImmutable();\n }\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds\n .selectorToFacetAndPosition[_selector]\n .functionSelectorPosition;\n uint256 lastSelectorPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors\n .length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds\n .facetFunctionSelectors[_facetAddress]\n .functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[\n selectorPosition\n ] = lastSelector;\n ds\n .selectorToFacetAndPosition[lastSelector]\n .functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[\n lastFacetAddressPosition\n ];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds\n .facetFunctionSelectors[lastFacetAddress]\n .facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds\n .facetFunctionSelectors[_facetAddress]\n .facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(\n address _init,\n bytes memory _calldata\n ) internal {\n if (LibUtil.isZeroAddress(_init)) {\n if (_calldata.length != 0) {\n revert InitZeroButCalldataNotEmpty();\n }\n } else {\n if (_calldata.length == 0) {\n revert CalldataEmptyButInitNotZero();\n }\n if (_init != address(this)) {\n enforceHasContractCode(_init);\n }\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert InitReverted();\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract) internal view {\n uint256 contractSize;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n contractSize := extcodesize(_contract)\n }\n if (contractSize == 0) {\n revert FacetContainsNoCode();\n }\n }\n}\n" + }, + "src/Libraries/LibAsset.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.17;\nimport { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from \"../Errors/GenericErrors.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { LibSwap } from \"./LibSwap.sol\";\n\n/// @title LibAsset\n/// @custom:version 1.0.2\n/// @notice This library contains helpers for dealing with onchain transfers\n/// of assets, including accounting for the native asset `assetId`\n/// conventions and any noncompliant ERC20 transfers\nlibrary LibAsset {\n uint256 private constant MAX_UINT = type(uint256).max;\n\n address internal constant NULL_ADDRESS = address(0);\n\n address internal constant NON_EVM_ADDRESS =\n 0x11f111f111f111F111f111f111F111f111f111F1;\n\n /// @dev All native assets use the empty address for their asset id\n /// by convention\n\n address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)\n\n /// @notice Gets the balance of the inheriting contract for the given asset\n /// @param assetId The asset identifier to get the balance of\n /// @return Balance held by contracts using this library\n function getOwnBalance(address assetId) internal view returns (uint256) {\n return\n isNativeAsset(assetId)\n ? address(this).balance\n : IERC20(assetId).balanceOf(address(this));\n }\n\n /// @notice Transfers ether from the inheriting contract to a given\n /// recipient\n /// @param recipient Address to send ether to\n /// @param amount Amount to send to given recipient\n function transferNativeAsset(\n address payable recipient,\n uint256 amount\n ) private {\n if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();\n if (amount > address(this).balance)\n revert InsufficientBalance(amount, address(this).balance);\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = recipient.call{ value: amount }(\"\");\n if (!success) revert NativeAssetTransferFailed();\n }\n\n /// @notice If the current allowance is insufficient, the allowance for a given spender\n /// is set to MAX_UINT.\n /// @param assetId Token address to transfer\n /// @param spender Address to give spend approval to\n /// @param amount Amount to approve for spending\n function maxApproveERC20(\n IERC20 assetId,\n address spender,\n uint256 amount\n ) internal {\n if (isNativeAsset(address(assetId))) {\n return;\n }\n if (spender == NULL_ADDRESS) {\n revert NullAddrIsNotAValidSpender();\n }\n\n if (assetId.allowance(address(this), spender) < amount) {\n SafeERC20.forceApprove(IERC20(assetId), spender, MAX_UINT);\n }\n }\n\n /// @notice Transfers tokens from the inheriting contract to a given\n /// recipient\n /// @param assetId Token address to transfer\n /// @param recipient Address to send token to\n /// @param amount Amount to send to given recipient\n function transferERC20(\n address assetId,\n address recipient,\n uint256 amount\n ) private {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (recipient == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n uint256 assetBalance = IERC20(assetId).balanceOf(address(this));\n if (amount > assetBalance) {\n revert InsufficientBalance(amount, assetBalance);\n }\n SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);\n }\n\n /// @notice Transfers tokens from a sender to a given recipient\n /// @param assetId Token address to transfer\n /// @param from Address of sender/owner\n /// @param to Address of recipient/spender\n /// @param amount Amount to transfer from owner to spender\n function transferFromERC20(\n address assetId,\n address from,\n address to,\n uint256 amount\n ) internal {\n if (isNativeAsset(assetId)) {\n revert NullAddrIsNotAnERC20Token();\n }\n if (to == NULL_ADDRESS) {\n revert NoTransferToNullAddress();\n }\n\n IERC20 asset = IERC20(assetId);\n uint256 prevBalance = asset.balanceOf(to);\n SafeERC20.safeTransferFrom(asset, from, to, amount);\n if (asset.balanceOf(to) - prevBalance != amount) {\n revert InvalidAmount();\n }\n }\n\n function depositAsset(address assetId, uint256 amount) internal {\n if (amount == 0) revert InvalidAmount();\n if (isNativeAsset(assetId)) {\n if (msg.value < amount) revert InvalidAmount();\n } else {\n uint256 balance = IERC20(assetId).balanceOf(msg.sender);\n if (balance < amount) revert InsufficientBalance(amount, balance);\n transferFromERC20(assetId, msg.sender, address(this), amount);\n }\n }\n\n function depositAssets(LibSwap.SwapData[] calldata swaps) internal {\n for (uint256 i = 0; i < swaps.length; ) {\n LibSwap.SwapData calldata swap = swaps[i];\n if (swap.requiresDeposit) {\n depositAsset(swap.sendingAssetId, swap.fromAmount);\n }\n unchecked {\n i++;\n }\n }\n }\n\n /// @notice Determines whether the given assetId is the native asset\n /// @param assetId The asset identifier to evaluate\n /// @return Boolean indicating if the asset is the native asset\n function isNativeAsset(address assetId) internal pure returns (bool) {\n return assetId == NATIVE_ASSETID;\n }\n\n /// @notice Wrapper function to transfer a given asset (native or erc20) to\n /// some recipient. Should handle all non-compliant return value\n /// tokens as well by using the SafeERC20 contract by open zeppelin.\n /// @param assetId Asset id for transfer (address(0) for native asset,\n /// token address for erc20s)\n /// @param recipient Address to send asset to\n /// @param amount Amount to send to given recipient\n function transferAsset(\n address assetId,\n address payable recipient,\n uint256 amount\n ) internal {\n isNativeAsset(assetId)\n ? transferNativeAsset(recipient, amount)\n : transferERC20(assetId, recipient, amount);\n }\n\n /// @dev Checks whether the given address is a contract and contains code\n function isContract(address _contractAddr) internal view returns (bool) {\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(_contractAddr)\n }\n return size > 0;\n }\n}\n" + }, + "src/Libraries/LibSwap.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { LibAsset } from \"./LibAsset.sol\";\nimport { LibUtil } from \"./LibUtil.sol\";\nimport { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from \"../Errors/GenericErrors.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LibSwap {\n struct SwapData {\n address callTo;\n address approveTo;\n address sendingAssetId;\n address receivingAssetId;\n uint256 fromAmount;\n bytes callData;\n bool requiresDeposit;\n }\n\n event AssetSwapped(\n bytes32 transactionId,\n address dex,\n address fromAssetId,\n address toAssetId,\n uint256 fromAmount,\n uint256 toAmount,\n uint256 timestamp\n );\n\n function swap(bytes32 transactionId, SwapData calldata _swap) internal {\n if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();\n uint256 fromAmount = _swap.fromAmount;\n if (fromAmount == 0) revert NoSwapFromZeroBalance();\n uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)\n ? _swap.fromAmount\n : 0;\n uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(\n _swap.sendingAssetId\n );\n uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(\n _swap.receivingAssetId\n );\n\n if (nativeValue == 0) {\n LibAsset.maxApproveERC20(\n IERC20(_swap.sendingAssetId),\n _swap.approveTo,\n _swap.fromAmount\n );\n }\n\n if (initialSendingAssetBalance < _swap.fromAmount) {\n revert InsufficientBalance(\n _swap.fromAmount,\n initialSendingAssetBalance\n );\n }\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory res) = _swap.callTo.call{\n value: nativeValue\n }(_swap.callData);\n if (!success) {\n LibUtil.revertWith(res);\n }\n\n uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);\n\n emit AssetSwapped(\n transactionId,\n _swap.callTo,\n _swap.sendingAssetId,\n _swap.receivingAssetId,\n _swap.fromAmount,\n newBalance > initialReceivingAssetBalance\n ? newBalance - initialReceivingAssetBalance\n : newBalance,\n block.timestamp\n );\n }\n}\n" + }, + "src/Helpers/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\n/// @title Reentrancy Guard\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide protection against reentrancy\nabstract contract ReentrancyGuard {\n /// Storage ///\n\n bytes32 private constant NAMESPACE = keccak256(\"com.lifi.reentrancyguard\");\n\n /// Types ///\n\n struct ReentrancyStorage {\n uint256 status;\n }\n\n /// Errors ///\n\n error ReentrancyError();\n\n /// Constants ///\n\n uint256 private constant _NOT_ENTERED = 0;\n uint256 private constant _ENTERED = 1;\n\n /// Modifiers ///\n\n modifier nonReentrant() {\n ReentrancyStorage storage s = reentrancyStorage();\n if (s.status == _ENTERED) revert ReentrancyError();\n s.status = _ENTERED;\n _;\n s.status = _NOT_ENTERED;\n }\n\n /// Private Methods ///\n\n /// @dev fetch local storage\n function reentrancyStorage()\n private\n pure\n returns (ReentrancyStorage storage data)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n data.slot := position\n }\n }\n}\n" + }, + "src/Helpers/SwapperV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibAllowList } from \"../Libraries/LibAllowList.sol\";\nimport { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from \"../Errors/GenericErrors.sol\";\n\n/// @title Swapper\n/// @author LI.FI (https://li.fi)\n/// @notice Abstract contract to provide swap functionality\ncontract SwapperV2 is ILiFi {\n /// Types ///\n\n /// @dev only used to get around \"Stack Too Deep\" errors\n struct ReserveData {\n bytes32 transactionId;\n address payable leftoverReceiver;\n uint256 nativeReserve;\n }\n\n /// Modifiers ///\n\n /// @dev Sends any leftover balances back to the user\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftovers(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Sends any leftover balances back to the user reserving native tokens\n /// @notice Sends any leftover balances to the user\n /// @param _swaps Swap data array\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial token balances\n modifier noLeftoversReserve(\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances,\n uint256 _nativeReserve\n ) {\n uint256 numSwaps = _swaps.length;\n if (numSwaps != 1) {\n address finalAsset = _swaps[numSwaps - 1].receivingAssetId;\n uint256 curBalance;\n\n _;\n\n for (uint256 i = 0; i < numSwaps - 1; ) {\n address curAsset = _swaps[i].receivingAssetId;\n // Handle multi-to-one swaps\n if (curAsset != finalAsset) {\n curBalance =\n LibAsset.getOwnBalance(curAsset) -\n _initialBalances[i];\n uint256 reserve = LibAsset.isNativeAsset(curAsset)\n ? _nativeReserve\n : 0;\n if (curBalance > 0) {\n LibAsset.transferAsset(\n curAsset,\n _leftoverReceiver,\n curBalance - reserve\n );\n }\n }\n unchecked {\n ++i;\n }\n }\n } else {\n _;\n }\n }\n\n /// @dev Refunds any excess native asset sent to the contract after the main function\n /// @notice Refunds any excess native asset sent to the contract after the main function\n /// @param _refundReceiver Address to send refunds to\n modifier refundExcessNative(address payable _refundReceiver) {\n uint256 initialBalance = address(this).balance - msg.value;\n _;\n uint256 finalBalance = address(this).balance;\n\n if (finalBalance > initialBalance) {\n LibAsset.transferAsset(\n LibAsset.NATIVE_ASSETID,\n _refundReceiver,\n finalBalance - initialBalance\n );\n }\n }\n\n /// Internal Methods ///\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @return uint256 result of the swap\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n _executeSwaps(\n _transactionId,\n _swaps,\n _leftoverReceiver,\n initialBalances\n );\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees\n /// @param _transactionId the transaction id associated with the operation\n /// @param _minAmount the minimum amount of the final asset to receive\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver The address to send leftover funds to\n /// @param _nativeReserve Amount of native token to prevent from being swept back to the caller\n function _depositAndSwap(\n bytes32 _transactionId,\n uint256 _minAmount,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256 _nativeReserve\n ) internal returns (uint256) {\n uint256 numSwaps = _swaps.length;\n\n if (numSwaps == 0) {\n revert NoSwapDataProvided();\n }\n\n address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;\n uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n initialBalance -= msg.value;\n }\n\n uint256[] memory initialBalances = _fetchBalances(_swaps);\n\n LibAsset.depositAssets(_swaps);\n ReserveData memory rd = ReserveData(\n _transactionId,\n _leftoverReceiver,\n _nativeReserve\n );\n _executeSwaps(rd, _swaps, initialBalances);\n\n uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -\n initialBalance;\n\n if (LibAsset.isNativeAsset(finalTokenId)) {\n newBalance -= _nativeReserve;\n }\n\n if (newBalance < _minAmount) {\n revert CumulativeSlippageTooHigh(_minAmount, newBalance);\n }\n\n return newBalance;\n }\n\n /// Private Methods ///\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _transactionId the transaction id associated with the operation\n /// @param _swaps Array of data used to execute swaps\n /// @param _leftoverReceiver Address to send leftover tokens to\n /// @param _initialBalances Array of initial balances\n function _executeSwaps(\n bytes32 _transactionId,\n LibSwap.SwapData[] calldata _swaps,\n address payable _leftoverReceiver,\n uint256[] memory _initialBalances\n ) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Executes swaps and checks that DEXs used are in the allowList\n /// @param _reserveData Data passed used to reserve native tokens\n /// @param _swaps Array of data used to execute swaps\n function _executeSwaps(\n ReserveData memory _reserveData,\n LibSwap.SwapData[] calldata _swaps,\n uint256[] memory _initialBalances\n )\n internal\n noLeftoversReserve(\n _swaps,\n _reserveData.leftoverReceiver,\n _initialBalances,\n _reserveData.nativeReserve\n )\n {\n uint256 numSwaps = _swaps.length;\n for (uint256 i = 0; i < numSwaps; ) {\n LibSwap.SwapData calldata currentSwap = _swaps[i];\n\n if (\n !((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||\n LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&\n LibAllowList.contractIsAllowed(currentSwap.callTo) &&\n LibAllowList.selectorIsAllowed(\n bytes4(currentSwap.callData[:4])\n ))\n ) revert ContractCallNotAllowed();\n\n LibSwap.swap(_reserveData.transactionId, currentSwap);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /// @dev Fetches balances of tokens to be swapped before swapping.\n /// @param _swaps Array of data used to execute swaps\n /// @return uint256[] Array of token balances.\n function _fetchBalances(\n LibSwap.SwapData[] calldata _swaps\n ) private view returns (uint256[] memory) {\n uint256 numSwaps = _swaps.length;\n uint256[] memory balances = new uint256[](numSwaps);\n address asset;\n for (uint256 i = 0; i < numSwaps; ) {\n asset = _swaps[i].receivingAssetId;\n balances[i] = LibAsset.getOwnBalance(asset);\n\n if (LibAsset.isNativeAsset(asset)) {\n balances[i] -= msg.value;\n }\n\n unchecked {\n ++i;\n }\n }\n\n return balances;\n }\n}\n" + }, + "src/Helpers/Validatable.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { LibAsset } from \"../Libraries/LibAsset.sol\";\nimport { LibUtil } from \"../Libraries/LibUtil.sol\";\nimport { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from \"../Errors/GenericErrors.sol\";\nimport { ILiFi } from \"../Interfaces/ILiFi.sol\";\nimport { LibSwap } from \"../Libraries/LibSwap.sol\";\n\ncontract Validatable {\n modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {\n if (LibUtil.isZeroAddress(_bridgeData.receiver)) {\n revert InvalidReceiver();\n }\n if (_bridgeData.minAmount == 0) {\n revert InvalidAmount();\n }\n if (_bridgeData.destinationChainId == block.chainid) {\n revert CannotBridgeToSameNetwork();\n }\n _;\n }\n\n modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {\n if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {\n revert NativeAssetNotSupported();\n }\n _;\n }\n\n modifier onlyAllowSourceToken(\n ILiFi.BridgeData memory _bridgeData,\n address _token\n ) {\n if (_bridgeData.sendingAssetId != _token) {\n revert InvalidSendingToken();\n }\n _;\n }\n\n modifier onlyAllowDestinationChain(\n ILiFi.BridgeData memory _bridgeData,\n uint256 _chainId\n ) {\n if (_bridgeData.destinationChainId != _chainId) {\n revert InvalidDestinationChain();\n }\n _;\n }\n\n modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (!_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {\n if (_bridgeData.hasSourceSwaps) {\n revert InformationMismatch();\n }\n _;\n }\n\n modifier doesNotContainDestinationCalls(\n ILiFi.BridgeData memory _bridgeData\n ) {\n if (_bridgeData.hasDestinationCall) {\n revert InformationMismatch();\n }\n _;\n }\n}\n" + }, + "src/Interfaces/IDlnSource.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\ninterface IDlnSource {\n struct OrderCreation {\n // the address of the ERC-20 token you are giving;\n // use the zero address to indicate you are giving a native blockchain token (ether, matic, etc).\n address giveTokenAddress;\n // the amount of tokens you are giving\n uint256 giveAmount;\n // the address of the ERC-20 token you are willing to take on the destination chain\n bytes takeTokenAddress;\n // the amount of tokens you are willing to take on the destination chain\n uint256 takeAmount;\n // the ID of the chain where an order should be fulfilled.\n // Use the list of supported chains mentioned above\n uint256 takeChainId;\n // the address on the destination chain where the funds\n // should be sent to upon order fulfillment\n bytes receiverDst;\n // the address on the source (current) chain who is allowed to patch the order\n // giving more input tokens and thus making the order more attractive to takers, just in case\n address givePatchAuthoritySrc;\n // the address on the destination chain who is allowed to patch the order\n // decreasing the take amount and thus making the order more attractive to takers, just in case\n bytes orderAuthorityAddressDst;\n // an optional address restricting anyone in the open market from fulfilling\n // this order but the given address. This can be useful if you are creating a order\n // for a specific taker. By default, set to empty bytes array (0x)\n bytes allowedTakerDst; // *optional\n // set to an empty bytes array (0x)\n bytes externalCall; // N/A, *optional\n // an optional address on the source (current) chain where the given input tokens\n // would be transferred to in case order cancellation is initiated by the orderAuthorityAddressDst\n // on the destination chain. This property can be safely set to an empty bytes array (0x):\n // in this case, tokens would be transferred to the arbitrary address specified\n // by the orderAuthorityAddressDst upon order cancellation\n bytes allowedCancelBeneficiarySrc; // *optional\n }\n\n function globalFixedNativeFee() external returns (uint256);\n\n function createOrder(\n OrderCreation calldata _orderCreation,\n bytes calldata _affiliateFee,\n uint32 _referralCode,\n bytes calldata _permitEnvelope\n ) external payable returns (bytes32 orderId);\n}\n" + }, + "src/Errors/GenericErrors.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nerror AlreadyInitialized();\nerror CannotAuthoriseSelf();\nerror CannotBridgeToSameNetwork();\nerror ContractCallNotAllowed();\nerror CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount);\nerror DiamondIsPaused();\nerror ExternalCallFailed();\nerror FunctionDoesNotExist();\nerror InformationMismatch();\nerror InsufficientBalance(uint256 required, uint256 balance);\nerror InvalidAmount();\nerror InvalidCallData();\nerror InvalidConfig();\nerror InvalidContract();\nerror InvalidDestinationChain();\nerror InvalidFallbackAddress();\nerror InvalidReceiver();\nerror InvalidSendingToken();\nerror NativeAssetNotSupported();\nerror NativeAssetTransferFailed();\nerror NoSwapDataProvided();\nerror NoSwapFromZeroBalance();\nerror NotAContract();\nerror NotInitialized();\nerror NoTransferToNullAddress();\nerror NullAddrIsNotAnERC20Token();\nerror NullAddrIsNotAValidSpender();\nerror OnlyContractOwner();\nerror RecoveryAddressCannotBeZero();\nerror ReentrancyError();\nerror TokenNotSupported();\nerror UnAuthorized();\nerror UnsupportedChainId(uint256 chainId);\nerror WithdrawFailed();\nerror ZeroAmount();\n" + }, + "src/Libraries/LibUtil.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport \"./LibBytes.sol\";\n\nlibrary LibUtil {\n using LibBytes for bytes;\n\n function getRevertMsg(\n bytes memory _res\n ) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_res.length < 68) return \"Transaction reverted silently\";\n bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes\n return abi.decode(revertData, (string)); // All that remains is the revert string\n }\n\n /// @notice Determines whether the given address is the zero address\n /// @param addr The address to verify\n /// @return Boolean indicating if the address is the zero address\n function isZeroAddress(address addr) internal pure returns (bool) {\n return addr == address(0);\n }\n\n function revertWith(bytes memory data) internal pure {\n assembly {\n let dataSize := mload(data) // Load the size of the data\n let dataPtr := add(data, 0x20) // Advance data pointer to the next word\n revert(dataPtr, dataSize) // Revert with the given data\n }\n }\n}\n" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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. Compatible with tokens that require the approval to be set to\n * 0 before setting it to a non-zero value.\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" + }, + "lib/openzeppelin-contracts/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" + }, + "src/Libraries/LibAllowList.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nimport { InvalidContract } from \"../Errors/GenericErrors.sol\";\n\n/// @title Lib Allow List\n/// @author LI.FI (https://li.fi)\n/// @notice Library for managing and accessing the conract address allow list\nlibrary LibAllowList {\n /// Storage ///\n bytes32 internal constant NAMESPACE =\n keccak256(\"com.lifi.library.allow.list\");\n\n struct AllowListStorage {\n mapping(address => bool) allowlist;\n mapping(bytes4 => bool) selectorAllowList;\n address[] contracts;\n }\n\n /// @dev Adds a contract address to the allow list\n /// @param _contract the contract address to add\n function addAllowedContract(address _contract) internal {\n _checkAddress(_contract);\n\n AllowListStorage storage als = _getStorage();\n\n if (als.allowlist[_contract]) return;\n\n als.allowlist[_contract] = true;\n als.contracts.push(_contract);\n }\n\n /// @dev Checks whether a contract address has been added to the allow list\n /// @param _contract the contract address to check\n function contractIsAllowed(\n address _contract\n ) internal view returns (bool) {\n return _getStorage().allowlist[_contract];\n }\n\n /// @dev Remove a contract address from the allow list\n /// @param _contract the contract address to remove\n function removeAllowedContract(address _contract) internal {\n AllowListStorage storage als = _getStorage();\n\n if (!als.allowlist[_contract]) {\n return;\n }\n\n als.allowlist[_contract] = false;\n\n uint256 length = als.contracts.length;\n // Find the contract in the list\n for (uint256 i = 0; i < length; i++) {\n if (als.contracts[i] == _contract) {\n // Move the last element into the place to delete\n als.contracts[i] = als.contracts[length - 1];\n // Remove the last element\n als.contracts.pop();\n break;\n }\n }\n }\n\n /// @dev Fetch contract addresses from the allow list\n function getAllowedContracts() internal view returns (address[] memory) {\n return _getStorage().contracts;\n }\n\n /// @dev Add a selector to the allow list\n /// @param _selector the selector to add\n function addAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = true;\n }\n\n /// @dev Removes a selector from the allow list\n /// @param _selector the selector to remove\n function removeAllowedSelector(bytes4 _selector) internal {\n _getStorage().selectorAllowList[_selector] = false;\n }\n\n /// @dev Returns if selector has been added to the allow list\n /// @param _selector the selector to check\n function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {\n return _getStorage().selectorAllowList[_selector];\n }\n\n /// @dev Fetch local storage struct\n function _getStorage()\n internal\n pure\n returns (AllowListStorage storage als)\n {\n bytes32 position = NAMESPACE;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n als.slot := position\n }\n }\n\n /// @dev Contains business logic for validating a contract address.\n /// @param _contract address of the dex to check\n function _checkAddress(address _contract) private view {\n if (_contract == address(0)) revert InvalidContract();\n\n if (_contract.code.length == 0) revert InvalidContract();\n }\n}\n" + }, + "src/Libraries/LibBytes.sol": { + "content": "// SPDX-License-Identifier: MIT\n/// @custom:version 1.0.0\npragma solidity ^0.8.17;\n\nlibrary LibBytes {\n // solhint-disable no-inline-assembly\n\n // LibBytes specific errors\n error SliceOverflow();\n error SliceOutOfBounds();\n error AddressOutOfBounds();\n\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n\n // -------------------------\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n if (_length + 31 < _length) revert SliceOverflow();\n if (_bytes.length < _start + _length) revert SliceOutOfBounds();\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(\n add(tempBytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n )\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(\n add(\n add(_bytes, lengthmod),\n mul(0x20, iszero(lengthmod))\n ),\n _start\n )\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(\n bytes memory _bytes,\n uint256 _start\n ) internal pure returns (address) {\n if (_bytes.length < _start + 20) {\n revert AddressOutOfBounds();\n }\n address tempAddress;\n\n assembly {\n tempAddress := div(\n mload(add(add(_bytes, 0x20), _start)),\n 0x1000000000000000000000000\n )\n }\n\n return tempAddress;\n }\n\n /// Copied from OpenZeppelin's `Strings.sol` utility library.\n /// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol\n function toHexString(\n uint256 value,\n uint256 length\n ) 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" + }, + "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 */\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 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" + }, + "lib/openzeppelin-contracts/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" + } + }, + "settings": { + "remappings": [ + "@eth-optimism/=node_modules/@hop-protocol/sdk/node_modules/@eth-optimism/", + "@uniswap/=node_modules/@uniswap/", + "eth-gas-reporter/=node_modules/eth-gas-reporter/", + "hardhat/=node_modules/hardhat/", + "hardhat-deploy/=node_modules/hardhat-deploy/", + "@openzeppelin/=lib/openzeppelin-contracts/", + "celer-network/=lib/sgn-v2-contracts/", + "create3-factory/=lib/create3-factory/src/", + "solmate/=lib/solmate/src/", + "solady/=lib/solady/src/", + "permit2/=lib/Permit2/src/", + "ds-test/=lib/ds-test/src/", + "forge-std/=lib/forge-std/src/", + "lifi/=src/", + "test/=test/", + "Permit2/=lib/Permit2/", + "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", + "forge-gas-snapshot/=lib/Permit2/lib/forge-gas-snapshot/src/", + "openzeppelin-contracts/=lib/openzeppelin-contracts/", + "openzeppelin/=lib/openzeppelin-contracts/contracts/", + "sgn-v2-contracts/=lib/sgn-v2-contracts/contracts/" + ], + "optimizer": { + "enabled": true, + "runs": 1000000 + }, + "metadata": { + "useLiteralContent": false, + "bytecodeHash": "ipfs" + }, + "outputSelection": { + "*": { + "*": [ + "evm.bytecode", + "evm.deployedBytecode", + "devdoc", + "userdoc", + "metadata", + "abi" + ] + } + }, + "evmVersion": "london", + "viaIR": false, + "libraries": {} + } +}} +1.0.0 + Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Verifying diamond file facets against deploy log... \ Verifying diamond file facets against deploy log... | Verifying diamond file facets against deploy log... / Verifying diamond file facets against deploy log... - Diamond file facets verification complete. ✔ +Verifying missing entries in diamond file... - Missing diamond file entries verification complete. ✔ +ℹ +=== On-chain vs. deploy log verification table === + +┌──────────┬───────────────────────────────────┬──────────────────────────────────────────────────┬──────────────────────────────────────────────────┬──────────┬────────────────────────────────────────────────────────────┐ +│ Issue ID │ Facet │ On-Chain Address │ Deploy Log Address │ Status │ Action / Description │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 1 │ DiamondCutFacet │ 0xf7993A8df974AD022647E63402d6315137c58ABf │ 0xaD50118509eB4c8e3E39a370151B0fD5D5957013 │ ERROR │ Facet "DiamondCutFacet": Address mismatch: on-chain │ +│ │ │ │ │ │ (0xf7993a8df974ad022647e63402d6315137c58abf) vs deploy log │ +│ │ │ │ │ │ (0xad50118509eb4c8e3e39a370151b0fd5d5957013). Deploy log │ +│ │ │ │ │ │ version (1.0.0) is newer than on-chain version (none). │ +│ │ │ │ │ │ Please register facet from deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 2 │ DiamondLoupeFacet │ 0xF5ba8Db6fEA7aF820De35C8D0c294e17DBC1b9D2 │ 0xc21a00a346d5b29955449Ca912343a3bB4c5552f │ ERROR │ Facet "DiamondLoupeFacet": Address mismatch: on-chain │ +│ │ │ │ │ │ (0xf5ba8db6fea7af820de35c8d0c294e17dbc1b9d2) vs deploy log │ +│ │ │ │ │ │ (0xc21a00a346d5b29955449ca912343a3bb4c5552f). Deploy log │ +│ │ │ │ │ │ version (1.0.0) is newer than on-chain version (none). │ +│ │ │ │ │ │ Please register facet from deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 3 │ OwnershipFacet │ 0x6faA6906b9e4A59020e673910105567e809789E0 │ 0x6faA6906b9e4A59020e673910105567e809789E0 │ SUCCESS │ Facet "OwnershipFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 4 │ AcrossFacetPacked │ 0xE397c4883ec89ed4Fc9D258F00C689708b2799c9 │ 0xE397c4883ec89ed4Fc9D258F00C689708b2799c9 │ SUCCESS │ Facet "AcrossFacetPacked": Addresses match and versions │ +│ │ │ │ │ │ are consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 5 │ DexManagerFacet │ 0x22B31a1a81d5e594315c866616db793E799556c5 │ 0x22B31a1a81d5e594315c866616db793E799556c5 │ SUCCESS │ Facet "DexManagerFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 6 │ AccessManagerFacet │ 0x77A13abB679A0DAFB4435D1Fa4cCC95D1ab51cfc │ 0x77A13abB679A0DAFB4435D1Fa4cCC95D1ab51cfc │ SUCCESS │ Facet "AccessManagerFacet": Addresses match and versions │ +│ │ │ │ │ │ are consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 7 │ unknown │ 0x0b5726b7348efBdA8620D5C374F85Cbe8f040B6a │ N/A │ ERROR │ Contract not verified and name not found in deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 8 │ AmarokFacet │ 0x3F95b05a77FDC6D82162D86A72b156b55030627f │ 0x3F95b05a77FDC6D82162D86A72b156b55030627f │ SUCCESS │ Facet "AmarokFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 9 │ CBridgeFacet │ 0x3b70Eb33948Fbfdc3f2F2491b96DFB1Aa18054E0 │ 0x3b70Eb33948Fbfdc3f2F2491b96DFB1Aa18054E0 │ SUCCESS │ Facet "CBridgeFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 10 │ GnosisBridgeFacet │ 0x0eF01249E2731082A078C0B3f408c2929c90Ac9c │ 0x0eF01249E2731082A078C0B3f408c2929c90Ac9c │ SUCCESS │ Facet "GnosisBridgeFacet": Addresses match and versions │ +│ │ │ │ │ │ are consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 11 │ ArbitrumBridgeFacet │ 0x090e074bc934c4D8B84e168cb6597e87Da0C019b │ 0x090e074bc934c4D8B84e168cb6597e87Da0C019b │ SUCCESS │ Facet "ArbitrumBridgeFacet": Addresses match and versions │ +│ │ │ │ │ │ are consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 12 │ HyphenFacet │ 0xF2c63815eBD0c4E048eF216C77E2c80aa4ecD59c │ 0xF2c63815eBD0c4E048eF216C77E2c80aa4ecD59c │ ERROR │ Contract file found in archive; please remove contract │ +│ │ │ │ │ │ from diamond and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 13 │ MultichainFacet │ 0x02063A0d7a222c16D5b63213262596B83b07150c │ 0x02063A0d7a222c16D5b63213262596B83b07150c │ ERROR │ Contract file found in archive; please remove contract │ +│ │ │ │ │ │ from diamond and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 14 │ AcrossFacet │ 0xBeE13d99dD633fEAa2a0935f00CbC859F8305FA7 │ 0xBeE13d99dD633fEAa2a0935f00CbC859F8305FA7 │ SUCCESS │ Facet "AcrossFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 15 │ OmniBridgeFacet │ 0x3C826D17B47DB69E1a9C1e32E10768d3709f1b9A │ 0x3C826D17B47DB69E1a9C1e32E10768d3709f1b9A │ SUCCESS │ Facet "OmniBridgeFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 16 │ OptimismBridgeFacet │ 0x87C10910DA7258E55dA2C5d43739fB68B12E6a4b │ 0x05d3a1c8FBd66121F142C368F58EC7800eD95A70 │ ERROR │ Facet "OptimismBridgeFacet": Address mismatch: on-chain │ +│ │ │ │ │ │ (0x87c10910da7258e55da2c5d43739fb68b12e6a4b) vs deploy log │ +│ │ │ │ │ │ (0x05d3a1c8fbd66121f142c368f58ec7800ed95a70). Deploy log │ +│ │ │ │ │ │ version (1.0.0) is newer than on-chain version (none). │ +│ │ │ │ │ │ Please register facet from deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 17 │ PolygonBridgeFacet │ 0xF609fdBA8f7A020975a7c82C82f6A1f526F9A8fC │ 0xF609fdBA8f7A020975a7c82C82f6A1f526F9A8fC │ SUCCESS │ Facet "PolygonBridgeFacet": Addresses match and versions │ +│ │ │ │ │ │ are consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 18 │ StargateFacet │ 0x7D1940fDfF0B37c137B105ce7967B3B86DB42648 │ 0x7D1940fDfF0B37c137B105ce7967B3B86DB42648 │ INFO │ Contract not verified. Assumed contract name │ +│ │ │ │ │ │ "StargateFacet" from deploy log. Facet "StargateFacet": │ +│ │ │ │ │ │ Repo version (2.2.0) is newer than on-chain (none). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 19 │ PeripheryRegistryFacet │ 0x69cb467EfD8044ac9eDB88F363309ab1cbFA0A15 │ 0x69cb467EfD8044ac9eDB88F363309ab1cbFA0A15 │ SUCCESS │ Facet "PeripheryRegistryFacet": Addresses match and │ +│ │ │ │ │ │ versions are consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 20 │ GenericSwapFacet │ 0x2b7D2C78bd801Cc06DDCF91DeE2e8fAE22814f7e │ 0x2b7D2C78bd801Cc06DDCF91DeE2e8fAE22814f7e │ SUCCESS │ Facet "GenericSwapFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 21 │ HopFacet │ 0xd84d9A8Bf830496C4DEc917bC27D22E09E01cB8A │ 0xd84d9A8Bf830496C4DEc917bC27D22E09E01cB8A │ SUCCESS │ Facet "HopFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 22 │ HopFacetOptimized │ 0x7D507e6E89C52aE610b8D0151c8cb24c24e43bdb │ 0x7D507e6E89C52aE610b8D0151c8cb24c24e43bdb │ SUCCESS │ Facet "HopFacetOptimized": Addresses match and versions │ +│ │ │ │ │ │ are consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 23 │ LIFuelFacet │ 0x66861f292099cAF644F4A8b6091De49BEC5E8a15 │ 0x66861f292099cAF644F4A8b6091De49BEC5E8a15 │ SUCCESS │ Facet "LIFuelFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 24 │ CBridgeFacetPacked │ 0xE7Bf43C55551B1036e796E7Fd3b125d1F9903e2E │ 0xE7Bf43C55551B1036e796E7Fd3b125d1F9903e2E │ SUCCESS │ Facet "CBridgeFacetPacked": Addresses match and versions │ +│ │ │ │ │ │ are consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 25 │ AllBridgeFacet │ 0xC0c42d148241c5b5BB38e974d40Fc9087f7F9ecD │ 0xC0c42d148241c5b5BB38e974d40Fc9087f7F9ecD │ SUCCESS │ Facet "AllBridgeFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 26 │ HopFacetPacked │ 0x6eF81a18E1E432C289DC0d1a670B78E8bbF9AA35 │ 0x6eF81a18E1E432C289DC0d1a670B78E8bbF9AA35 │ SUCCESS │ Facet "HopFacetPacked": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 27 │ CelerCircleBridgeFacet │ 0x6731C946747bA54c78e7a65d416Cde39E478ECeb │ 0x6731C946747bA54c78e7a65d416Cde39E478ECeb │ SUCCESS │ Facet "CelerCircleBridgeFacet": Addresses match and │ +│ │ │ │ │ │ versions are consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 28 │ CelerIMFacetMutable │ 0xF70A1Ed85EcC454a562A4B69ee40CBc6a4eB0b64 │ 0xF70A1Ed85EcC454a562A4B69ee40CBc6a4eB0b64 │ SUCCESS │ Facet "CelerIMFacetMutable": Addresses match and versions │ +│ │ │ │ │ │ are consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 29 │ StandardizedCallFacet │ 0x175E7799DA0CD40E641352EaB90D8e39e02a4Ca9 │ 0x175E7799DA0CD40E641352EaB90D8e39e02a4Ca9 │ SUCCESS │ Facet "StandardizedCallFacet": Addresses match and │ +│ │ │ │ │ │ versions are consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 30 │ CalldataVerificationFacet │ 0x7A5c119ec5dDbF9631cf40f6e5DB28f31d4332a0 │ 0x7A5c119ec5dDbF9631cf40f6e5DB28f31d4332a0 │ INFO │ Facet "CalldataVerificationFacet": Repo version (1.2.0) is │ +│ │ │ │ │ │ newer than on-chain (1.1.1). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 31 │ RelayFacet │ 0x424BDbbaEda89732443fb1B737b6Dc194a6Ddbd5 │ 0x424BDbbaEda89732443fb1B737b6Dc194a6Ddbd5 │ SUCCESS │ Facet "RelayFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 32 │ ThorSwapFacet │ 0x3c0727E3Ab7BAf3a4205f518f1b7570d68Da19ba │ 0x3c0727E3Ab7BAf3a4205f518f1b7570d68Da19ba │ SUCCESS │ Facet "ThorSwapFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 33 │ WithdrawFacet │ 0x711e80A9c1eB906d9Ae9d37E5432E6E7aCeEdA0B │ 0x711e80A9c1eB906d9Ae9d37E5432E6E7aCeEdA0B │ SUCCESS │ Facet "WithdrawFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 34 │ GenericSwapFacetV3 │ 0x31a9b1835864706Af10103b31Ea2b79bdb995F5F │ 0x31a9b1835864706Af10103b31Ea2b79bdb995F5F │ INFO │ Facet "GenericSwapFacetV3": Repo version (1.0.1) is newer │ +│ │ │ │ │ │ than on-chain (1.0.0). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 35 │ AmarokFacetPacked │ 0xF18A285f4e6f720Eb9b4e05df71f88b9552E6ADB │ 0xF18A285f4e6f720Eb9b4e05df71f88b9552E6ADB │ SUCCESS │ Facet "AmarokFacetPacked": Addresses match and versions │ +│ │ │ │ │ │ are consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 36 │ SymbiosisFacet │ 0xe12b2488c71432F9a116E9ac244D3Ef4c2386d3a │ 0xe12b2488c71432F9a116E9ac244D3Ef4c2386d3a │ SUCCESS │ Facet "SymbiosisFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 37 │ SquidFacet │ 0x5C2C3F56e33F45389aa4e1DA4D3a807A532a910c │ 0x5C2C3F56e33F45389aa4e1DA4D3a807A532a910c │ SUCCESS │ Facet "SquidFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 38 │ MayanFacet │ 0x4682d79DD4D0e7555415841b5151933AF50594A8 │ 0x4682d79DD4D0e7555415841b5151933AF50594A8 │ SUCCESS │ Facet "MayanFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 39 │ StargateFacetV2 │ 0x6e378C84e657C57b2a8d183CFf30ee5CC8989b61 │ 0x6e378C84e657C57b2a8d183CFf30ee5CC8989b61 │ SUCCESS │ Facet "StargateFacetV2": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 40 │ AcrossFacetPackedV3 │ 0x21a786957c69424A4353Afe743242Bd9Db3cC07b │ 0x21a786957c69424A4353Afe743242Bd9Db3cC07b │ SUCCESS │ Facet "AcrossFacetPackedV3": Addresses match and versions │ +│ │ │ │ │ │ are consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 41 │ AcrossFacetV3 │ 0x5052fc5c7486162deDf7458E1f7c6ABaFbcd6895 │ 0x5052fc5c7486162deDf7458E1f7c6ABaFbcd6895 │ SUCCESS │ Facet "AcrossFacetV3": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 42 │ EmergencyPauseFacet │ 0x6F2baA7cd5F156CA1B132F7FF11E0fa2aD775F61 │ 0x6F2baA7cd5F156CA1B132F7FF11E0fa2aD775F61 │ INFO │ Facet "EmergencyPauseFacet": Repo version (1.0.1) is newer │ +│ │ │ │ │ │ than on-chain (1.0.0). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 43 │ GasZipFacet │ 0xF5c923a087fb3c554579e2DD10AB6E37E0f6F849 │ 0xF5c923a087fb3c554579e2DD10AB6E37E0f6F849 │ INFO │ Facet "GasZipFacet": Repo version (2.0.2) is newer than │ +│ │ │ │ │ │ on-chain (2.0.0). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 44 │ DeBridgeDlnFacet │ 0x18C85B940c29ECC3c210Ea40a5B6d91F5aeE2803 │ 0x18C85B940c29ECC3c210Ea40a5B6d91F5aeE2803 │ SUCCESS │ Facet "DeBridgeDlnFacet": Addresses match and versions are │ +│ │ │ │ │ │ consistent. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 45 │ AxelarFacet │ N/A │ 0x55c51beF79d16F5f0875E11207B17E885c21c13d │ ERROR │ Facet "AxelarFacet" is present in deploy log but not │ +│ │ │ │ │ │ fetched on-chain. Contract file found in archive; please │ +│ │ │ │ │ │ remove contract from diamond and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 46 │ NXTPFacet │ N/A │ 0x238502aDc8ca550723CBE78543c8B757599A21cC │ ERROR │ Facet "NXTPFacet" is present in deploy log but not fetched │ +│ │ │ │ │ │ on-chain. Contract file found in archive; please remove │ +│ │ │ │ │ │ contract from diamond and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 47 │ GetGasFacet │ N/A │ 0x50b4cB2C152322760a8fA59105A46745CE2B7Eac │ ERROR │ Facet "GetGasFacet" is present in deploy log but not │ +│ │ │ │ │ │ fetched on-chain. Contract file not found in src. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 48 │ CelerIMFacetImmutable │ N/A │ 0x0d26d248D4e80377f1d794AB88090e76B0903EDE │ ERROR │ Facet "CelerIMFacetImmutable" is present in deploy log but │ +│ │ │ │ │ │ not fetched on-chain. Contract file found in archive; │ +│ │ │ │ │ │ please remove contract from diamond and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 49 │ WormholeFacet │ N/A │ 0x52a29e1f32DEd47B6FfF036e95667125921faE50 │ ERROR │ Facet "WormholeFacet" is present in deploy log but not │ +│ │ │ │ │ │ fetched on-chain. Contract file found in archive; please │ +│ │ │ │ │ │ remove contract from diamond and deploy log. │ +└──────────┴───────────────────────────────────┴──────────────────────────────────────────────────┴──────────────────────────────────────────────────┴──────────┴────────────────────────────────────────────────────────────┘ +ℹ +=== Diamond file vs. deploy log verification table === + +┌──────────┬───────────────────────────────────┬──────────────────────────────────────────────────┬──────────────────────────────────────────────────┬──────────┬────────────────────────────────────────────────────────────┐ +│ Issue ID │ Facet │ Diamond Log Address │ Deploy Log Address │ Status │ Action / Description │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 1 │ DiamondCutFacet │ 0xf7993A8df974AD022647E63402d6315137c58ABf │ 0xaD50118509eB4c8e3E39a370151B0fD5D5957013 │ ERROR │ Diamond log contract verified as "DiamondCutFacet". │ +│ │ │ │ │ │ Address mismatch for facet "DiamondCutFacet": diamond file │ +│ │ │ │ │ │ shows (0xf7993a8df974ad022647e63402d6315137c58abf) vs │ +│ │ │ │ │ │ deploy log (0xad50118509eb4c8e3e39a370151b0fd5d5957013). │ +│ │ │ │ │ │ Deploy log version (1.0.0) is newer than on-chain diamond │ +│ │ │ │ │ │ version (none). Please register facet from deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 2 │ OwnershipFacet │ 0x6faA6906b9e4A59020e673910105567e809789E0 │ 0x6faA6906b9e4A59020e673910105567e809789E0 │ SUCCESS │ Facet "OwnershipFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 3 │ AcrossFacetPacked │ 0xE397c4883ec89ed4Fc9D258F00C689708b2799c9 │ 0xE397c4883ec89ed4Fc9D258F00C689708b2799c9 │ SUCCESS │ Facet "AcrossFacetPacked" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 4 │ DexManagerFacet │ 0x22B31a1a81d5e594315c866616db793E799556c5 │ 0x22B31a1a81d5e594315c866616db793E799556c5 │ SUCCESS │ Facet "DexManagerFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 5 │ AccessManagerFacet │ 0x77A13abB679A0DAFB4435D1Fa4cCC95D1ab51cfc │ 0x77A13abB679A0DAFB4435D1Fa4cCC95D1ab51cfc │ SUCCESS │ Facet "AccessManagerFacet" matches between diamond file │ +│ │ │ │ │ │ and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 6 │ AmarokFacet │ 0x3F95b05a77FDC6D82162D86A72b156b55030627f │ 0x3F95b05a77FDC6D82162D86A72b156b55030627f │ SUCCESS │ Facet "AmarokFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 7 │ CBridgeFacet │ 0x3b70Eb33948Fbfdc3f2F2491b96DFB1Aa18054E0 │ 0x3b70Eb33948Fbfdc3f2F2491b96DFB1Aa18054E0 │ SUCCESS │ Facet "CBridgeFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 8 │ GnosisBridgeFacet │ 0x0eF01249E2731082A078C0B3f408c2929c90Ac9c │ 0x0eF01249E2731082A078C0B3f408c2929c90Ac9c │ SUCCESS │ Facet "GnosisBridgeFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 9 │ ArbitrumBridgeFacet │ 0x090e074bc934c4D8B84e168cb6597e87Da0C019b │ 0x090e074bc934c4D8B84e168cb6597e87Da0C019b │ SUCCESS │ Facet "ArbitrumBridgeFacet" matches between diamond file │ +│ │ │ │ │ │ and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 10 │ HyphenFacet │ 0xF2c63815eBD0c4E048eF216C77E2c80aa4ecD59c │ 0xF2c63815eBD0c4E048eF216C77E2c80aa4ecD59c │ ERROR │ Contract file found in archive; please remove contract │ +│ │ │ │ │ │ from diamond and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 11 │ MultichainFacet │ 0x02063A0d7a222c16D5b63213262596B83b07150c │ 0x02063A0d7a222c16D5b63213262596B83b07150c │ ERROR │ Contract file found in archive; please remove contract │ +│ │ │ │ │ │ from diamond and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 12 │ AcrossFacet │ 0xBeE13d99dD633fEAa2a0935f00CbC859F8305FA7 │ 0xBeE13d99dD633fEAa2a0935f00CbC859F8305FA7 │ SUCCESS │ Facet "AcrossFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 13 │ OmniBridgeFacet │ 0x3C826D17B47DB69E1a9C1e32E10768d3709f1b9A │ 0x3C826D17B47DB69E1a9C1e32E10768d3709f1b9A │ SUCCESS │ Facet "OmniBridgeFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 14 │ PolygonBridgeFacet │ 0xF609fdBA8f7A020975a7c82C82f6A1f526F9A8fC │ 0xF609fdBA8f7A020975a7c82C82f6A1f526F9A8fC │ SUCCESS │ Facet "PolygonBridgeFacet" matches between diamond file │ +│ │ │ │ │ │ and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 15 │ StargateFacet │ 0x7D1940fDfF0B37c137B105ce7967B3B86DB42648 │ 0x7D1940fDfF0B37c137B105ce7967B3B86DB42648 │ INFO │ Facet "StargateFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. Note: Diamond file version (2.2.0) does not │ +│ │ │ │ │ │ match on-chain version (none). Note: Diamond file version │ +│ │ │ │ │ │ (2.2.0) does not match on-chain version (none). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 16 │ PeripheryRegistryFacet │ 0x69cb467EfD8044ac9eDB88F363309ab1cbFA0A15 │ 0x69cb467EfD8044ac9eDB88F363309ab1cbFA0A15 │ SUCCESS │ Facet "PeripheryRegistryFacet" matches between diamond │ +│ │ │ │ │ │ file and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 17 │ GenericSwapFacet │ 0x2b7D2C78bd801Cc06DDCF91DeE2e8fAE22814f7e │ 0x2b7D2C78bd801Cc06DDCF91DeE2e8fAE22814f7e │ SUCCESS │ Facet "GenericSwapFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 18 │ HopFacet │ 0xd84d9A8Bf830496C4DEc917bC27D22E09E01cB8A │ 0xd84d9A8Bf830496C4DEc917bC27D22E09E01cB8A │ SUCCESS │ Facet "HopFacet" matches between diamond file and deploy │ +│ │ │ │ │ │ log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 19 │ HopFacetOptimized │ 0x7D507e6E89C52aE610b8D0151c8cb24c24e43bdb │ 0x7D507e6E89C52aE610b8D0151c8cb24c24e43bdb │ SUCCESS │ Facet "HopFacetOptimized" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 20 │ LIFuelFacet │ 0x66861f292099cAF644F4A8b6091De49BEC5E8a15 │ 0x66861f292099cAF644F4A8b6091De49BEC5E8a15 │ SUCCESS │ Facet "LIFuelFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 21 │ CBridgeFacetPacked │ 0xE7Bf43C55551B1036e796E7Fd3b125d1F9903e2E │ 0xE7Bf43C55551B1036e796E7Fd3b125d1F9903e2E │ SUCCESS │ Facet "CBridgeFacetPacked" matches between diamond file │ +│ │ │ │ │ │ and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 22 │ AllBridgeFacet │ 0xC0c42d148241c5b5BB38e974d40Fc9087f7F9ecD │ 0xC0c42d148241c5b5BB38e974d40Fc9087f7F9ecD │ SUCCESS │ Facet "AllBridgeFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 23 │ HopFacetPacked │ 0x6eF81a18E1E432C289DC0d1a670B78E8bbF9AA35 │ 0x6eF81a18E1E432C289DC0d1a670B78E8bbF9AA35 │ SUCCESS │ Facet "HopFacetPacked" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 24 │ CelerCircleBridgeFacet │ 0x6731C946747bA54c78e7a65d416Cde39E478ECeb │ 0x6731C946747bA54c78e7a65d416Cde39E478ECeb │ SUCCESS │ Facet "CelerCircleBridgeFacet" matches between diamond │ +│ │ │ │ │ │ file and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 25 │ CelerIMFacetMutable │ 0xF70A1Ed85EcC454a562A4B69ee40CBc6a4eB0b64 │ 0xF70A1Ed85EcC454a562A4B69ee40CBc6a4eB0b64 │ SUCCESS │ Facet "CelerIMFacetMutable" matches between diamond file │ +│ │ │ │ │ │ and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 26 │ StandardizedCallFacet │ 0x175E7799DA0CD40E641352EaB90D8e39e02a4Ca9 │ 0x175E7799DA0CD40E641352EaB90D8e39e02a4Ca9 │ SUCCESS │ Facet "StandardizedCallFacet" matches between diamond file │ +│ │ │ │ │ │ and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 27 │ CalldataVerificationFacet │ 0x7A5c119ec5dDbF9631cf40f6e5DB28f31d4332a0 │ 0x7A5c119ec5dDbF9631cf40f6e5DB28f31d4332a0 │ SUCCESS │ Facet "CalldataVerificationFacet" matches between diamond │ +│ │ │ │ │ │ file and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 28 │ RelayFacet │ 0x424BDbbaEda89732443fb1B737b6Dc194a6Ddbd5 │ 0x424BDbbaEda89732443fb1B737b6Dc194a6Ddbd5 │ SUCCESS │ Facet "RelayFacet" matches between diamond file and deploy │ +│ │ │ │ │ │ log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 29 │ ThorSwapFacet │ 0x3c0727E3Ab7BAf3a4205f518f1b7570d68Da19ba │ 0x3c0727E3Ab7BAf3a4205f518f1b7570d68Da19ba │ SUCCESS │ Facet "ThorSwapFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 30 │ WithdrawFacet │ 0x711e80A9c1eB906d9Ae9d37E5432E6E7aCeEdA0B │ 0x711e80A9c1eB906d9Ae9d37E5432E6E7aCeEdA0B │ SUCCESS │ Facet "WithdrawFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 31 │ GenericSwapFacetV3 │ 0x31a9b1835864706Af10103b31Ea2b79bdb995F5F │ 0x31a9b1835864706Af10103b31Ea2b79bdb995F5F │ SUCCESS │ Facet "GenericSwapFacetV3" matches between diamond file │ +│ │ │ │ │ │ and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 32 │ AmarokFacetPacked │ 0xF18A285f4e6f720Eb9b4e05df71f88b9552E6ADB │ 0xF18A285f4e6f720Eb9b4e05df71f88b9552E6ADB │ SUCCESS │ Facet "AmarokFacetPacked" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 33 │ SymbiosisFacet │ 0xe12b2488c71432F9a116E9ac244D3Ef4c2386d3a │ 0xe12b2488c71432F9a116E9ac244D3Ef4c2386d3a │ SUCCESS │ Facet "SymbiosisFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 34 │ SquidFacet │ 0x5C2C3F56e33F45389aa4e1DA4D3a807A532a910c │ 0x5C2C3F56e33F45389aa4e1DA4D3a807A532a910c │ SUCCESS │ Facet "SquidFacet" matches between diamond file and deploy │ +│ │ │ │ │ │ log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 35 │ MayanFacet │ 0x4682d79DD4D0e7555415841b5151933AF50594A8 │ 0x4682d79DD4D0e7555415841b5151933AF50594A8 │ SUCCESS │ Facet "MayanFacet" matches between diamond file and deploy │ +│ │ │ │ │ │ log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 36 │ StargateFacetV2 │ 0x6e378C84e657C57b2a8d183CFf30ee5CC8989b61 │ 0x6e378C84e657C57b2a8d183CFf30ee5CC8989b61 │ SUCCESS │ Facet "StargateFacetV2" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 37 │ AcrossFacetPackedV3 │ 0x21a786957c69424A4353Afe743242Bd9Db3cC07b │ 0x21a786957c69424A4353Afe743242Bd9Db3cC07b │ SUCCESS │ Facet "AcrossFacetPackedV3" matches between diamond file │ +│ │ │ │ │ │ and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 38 │ AcrossFacetV3 │ 0x5052fc5c7486162deDf7458E1f7c6ABaFbcd6895 │ 0x5052fc5c7486162deDf7458E1f7c6ABaFbcd6895 │ SUCCESS │ Facet "AcrossFacetV3" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 39 │ EmergencyPauseFacet │ 0x6F2baA7cd5F156CA1B132F7FF11E0fa2aD775F61 │ 0x6F2baA7cd5F156CA1B132F7FF11E0fa2aD775F61 │ SUCCESS │ Facet "EmergencyPauseFacet" matches between diamond file │ +│ │ │ │ │ │ and deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 40 │ GasZipFacet │ 0xF5c923a087fb3c554579e2DD10AB6E37E0f6F849 │ 0xF5c923a087fb3c554579e2DD10AB6E37E0f6F849 │ SUCCESS │ Facet "GasZipFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 41 │ DeBridgeDlnFacet │ 0x18C85B940c29ECC3c210Ea40a5B6d91F5aeE2803 │ 0x18C85B940c29ECC3c210Ea40a5B6d91F5aeE2803 │ SUCCESS │ Facet "DeBridgeDlnFacet" matches between diamond file and │ +│ │ │ │ │ │ deploy log. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 42 │ ERC20Proxy │ 0x5741A7FfE7c39Ca175546a54985fA79211290b51 │ 0x5741A7FfE7c39Ca175546a54985fA79211290b51 │ SUCCESS │ Periphery contract "ERC20Proxy" matches. Versions match │ +│ │ │ │ │ │ (1.0.0). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 43 │ Executor │ 0x2dfaDAB8266483beD9Fd9A292Ce56596a2D1378D │ 0x2dfaDAB8266483beD9Fd9A292Ce56596a2D1378D │ SUCCESS │ Periphery contract "Executor" matches. Versions match │ +│ │ │ │ │ │ (2.0.0). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 44 │ FeeCollector │ 0xbD6C7B0d2f68c2b7805d88388319cfB6EcB50eA9 │ 0xbD6C7B0d2f68c2b7805d88388319cfB6EcB50eA9 │ SUCCESS │ Periphery contract "FeeCollector" matches. Versions match │ +│ │ │ │ │ │ (none). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 45 │ GasZipPeriphery │ 0x9a21E33F1a78b17DAd32010CeDB9Fd2F071C17d3 │ 0x9a21E33F1a78b17DAd32010CeDB9Fd2F071C17d3 │ SUCCESS │ Periphery contract "GasZipPeriphery" matches. Versions │ +│ │ │ │ │ │ match (1.0.0). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 46 │ LiFiDEXAggregator │ 0x6140b987d6B51Fd75b66C3B07733Beb5167c42fc │ 0x6140b987d6B51Fd75b66C3B07733Beb5167c42fc │ SUCCESS │ Periphery contract "LiFiDEXAggregator" matches. Versions │ +│ │ │ │ │ │ match (1.0.0). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 47 │ LiFuelFeeCollector │ 0xc02FFcdD914DbA646704439c6090BAbaD521d04C │ 0xc02FFcdD914DbA646704439c6090BAbaD521d04C │ SUCCESS │ Periphery contract "LiFuelFeeCollector" matches. Versions │ +│ │ │ │ │ │ match (1.0.1). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 48 │ Permit2Proxy │ 0x6307119078556Fc8aD77781DFC67df20d75FB4f9 │ 0x6307119078556Fc8aD77781DFC67df20d75FB4f9 │ SUCCESS │ Periphery contract "Permit2Proxy" matches. Versions match │ +│ │ │ │ │ │ (1.0.0). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 49 │ ReceiverAcrossV3 │ 0xca6e6B692F568055adA0bF72A06D1EBbC938Fb23 │ 0xca6e6B692F568055adA0bF72A06D1EBbC938Fb23 │ SUCCESS │ Periphery contract "ReceiverAcrossV3" matches. Versions │ +│ │ │ │ │ │ match (1.0.1). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 50 │ Receiver │ 0x050e198E36A73a1e32F15C3afC58C4506d82f657 │ 0x050e198E36A73a1e32F15C3afC58C4506d82f657 │ SUCCESS │ Periphery contract "Receiver" matches. Versions match │ +│ │ │ │ │ │ (2.0.3). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 51 │ ReceiverStargateV2 │ 0x1493e7B8d4DfADe0a178dAD9335470337A3a219A │ 0x1493e7B8d4DfADe0a178dAD9335470337A3a219A │ SUCCESS │ Periphery contract "ReceiverStargateV2" matches. Versions │ +│ │ │ │ │ │ match (1.0.0). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 52 │ RelayerCelerIM │ 0x6a8b11bF29C0546991DEcD6E0Db8cC7Fda22bA97 │ 0x1C97BE47f6Da4d2e09B3A11B0A17C513dfD0e896 │ ERROR │ Periphery contract "RelayerCelerIM" mismatch: diamond log │ +│ │ │ │ │ │ (0x6a8b11bf29c0546991decd6e0db8cc7fda22ba97) vs deploy log │ +│ │ │ │ │ │ (0x1c97be47f6da4d2e09b3a11b0a17c513dfd0e896). Versions │ +│ │ │ │ │ │ identical (2.0.0) but addresses differ. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 53 │ TokenWrapper │ 0x5215E9fd223BC909083fbdB2860213873046e45d │ 0x5215E9fd223BC909083fbdB2860213873046e45d │ SUCCESS │ Periphery contract "TokenWrapper" matches. Versions match │ +│ │ │ │ │ │ (1.0.0). │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 54 │ DiamondCutFacet │ N/A │ 0xaD50118509eB4c8e3E39a370151B0fD5D5957013 │ WARN │ Facet "DiamondCutFacet" is present in deploy log but │ +│ │ │ │ │ │ missing in diamond file. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 55 │ DiamondLoupeFacet │ N/A │ 0xc21a00a346d5b29955449Ca912343a3bB4c5552f │ WARN │ Facet "DiamondLoupeFacet" is present in deploy log but │ +│ │ │ │ │ │ missing in diamond file. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 56 │ AxelarFacet │ N/A │ 0x55c51beF79d16F5f0875E11207B17E885c21c13d │ WARN │ Facet "AxelarFacet" is present in deploy log but missing │ +│ │ │ │ │ │ in diamond file. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 57 │ NXTPFacet │ N/A │ 0x238502aDc8ca550723CBE78543c8B757599A21cC │ WARN │ Facet "NXTPFacet" is present in deploy log but missing in │ +│ │ │ │ │ │ diamond file. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 58 │ OptimismBridgeFacet │ N/A │ 0x05d3a1c8FBd66121F142C368F58EC7800eD95A70 │ WARN │ Facet "OptimismBridgeFacet" is present in deploy log but │ +│ │ │ │ │ │ missing in diamond file. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 59 │ GetGasFacet │ N/A │ 0x50b4cB2C152322760a8fA59105A46745CE2B7Eac │ WARN │ Facet "GetGasFacet" is present in deploy log but missing │ +│ │ │ │ │ │ in diamond file. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 60 │ CelerIMFacetImmutable │ N/A │ 0x0d26d248D4e80377f1d794AB88090e76B0903EDE │ WARN │ Facet "CelerIMFacetImmutable" is present in deploy log but │ +│ │ │ │ │ │ missing in diamond file. │ +├──────────┼───────────────────────────────────┼──────────────────────────────────────────────────┼──────────────────────────────────────────────────┼──────────┼────────────────────────────────────────────────────────────┤ +│ 61 │ WormholeFacet │ N/A │ 0x52a29e1f32DEd47B6FfF036e95667125921faE50 │ WARN │ Facet "WormholeFacet" is present in deploy log but missing │ +│ │ │ │ │ │ in diamond file. │ +└──────────┴───────────────────────────────────┴──────────────────────────────────────────────────┴──────────────────────────────────────────────────┴──────────┴────────────────────────────────────────────────────────────┘ + Verification Process Completed. ✔ diff --git a/script/deploy/verifyNetworkDeploymentLogs.ts b/script/deploy/verifyNetworkDeploymentLogs.ts index 466897b68..62b53a5a4 100644 --- a/script/deploy/verifyNetworkDeploymentLogs.ts +++ b/script/deploy/verifyNetworkDeploymentLogs.ts @@ -478,15 +478,20 @@ async function verifyDiamondAgainstDeployLog({ ? formatVersion(extractVersion(chainDiamondData.SourceCode || '')) : NO_VERSION let versionNote = '' - // check if Version matches what's currently deployed onchain - if ( - !( - diamondFileVersion === NO_VERSION && - chainDiamondVersion === NO_VERSION - ) && - diamondFileVersion !== chainDiamondVersion - ) { - versionNote = ` Note: Diamond file version (${diamondFileVersion}) does not match on-chain version (${chainDiamondVersion}).` + // Only compare versions if the contract is verified. + if (chainDiamondData && chainDiamondData.ContractName) { + if ( + !( + diamondFileVersion === NO_VERSION && + chainDiamondVersion === NO_VERSION + ) && + diamondFileVersion !== chainDiamondVersion + ) { + versionNote = ` Note: Diamond file version (${diamondFileVersion}) does not match on-chain version (${chainDiamondVersion}).` + } + } else { + // If not verified, add a message stating that. + versionNote = ` Contract at ${diamondLogAddr} is not verified.` } let deployLogAddr = networkDeployLogContracts[facetName]?.toLowerCase() || NA