Source Code
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| Xcall | 21241131 | 472 days ago | 0.00000116 ETH | ||||
| Start Bridge Tok... | 21241131 | 472 days ago | 0.00000116 ETH | ||||
| Xcall | 21240784 | 472 days ago | 0.00000094 ETH | ||||
| Start Bridge Tok... | 21240784 | 472 days ago | 0.00000094 ETH | ||||
| Xcall | 21238670 | 473 days ago | 0.00000533 ETH | ||||
| Start Bridge Tok... | 21238670 | 473 days ago | 0.00000533 ETH | ||||
| Xcall | 20877346 | 523 days ago | 0.00000449 ETH | ||||
| Start Bridge Tok... | 20877346 | 523 days ago | 0.00000449 ETH | ||||
| Xcall | 20874477 | 523 days ago | 0.00000262 ETH | ||||
| Start Bridge Tok... | 20874477 | 523 days ago | 0.00000262 ETH | ||||
| Xcall | 20861295 | 525 days ago | 0.00000033 ETH | ||||
| Start Bridge Tok... | 20861295 | 525 days ago | 0.00000033 ETH | ||||
| Xcall | 20859588 | 526 days ago | 0.00021787 ETH | ||||
| Start Bridge Tok... | 20859588 | 526 days ago | 0.00021787 ETH | ||||
| Xcall | 20857340 | 526 days ago | 0.00022879 ETH | ||||
| Start Bridge Tok... | 20857340 | 526 days ago | 0.00022879 ETH | ||||
| Xcall | 20856534 | 526 days ago | 0.00020727 ETH | ||||
| Start Bridge Tok... | 20856534 | 526 days ago | 0.00020727 ETH | ||||
| Xcall | 20855931 | 526 days ago | 0.00019625 ETH | ||||
| Start Bridge Tok... | 20855931 | 526 days ago | 0.00019625 ETH | ||||
| Xcall | 20848926 | 527 days ago | 0.00002031 ETH | ||||
| Start Bridge Tok... | 20848926 | 527 days ago | 0.00002031 ETH | ||||
| Xcall | 20848139 | 527 days ago | 0.00000304 ETH | ||||
| Start Bridge Tok... | 20848139 | 527 days ago | 0.00000304 ETH | ||||
| Xcall | 20847156 | 527 days ago | 0.00000218 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AmarokFacetPacked
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// // SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import { IConnextHandler } from "../Interfaces/IConnextHandler.sol";
import { ILiFi } from "../Interfaces/ILiFi.sol";
import { ERC20, SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { LibAsset, IERC20 } from "../Libraries/LibAsset.sol";
import { TransferrableOwnership } from "../Helpers/TransferrableOwnership.sol";
import { AmarokFacet } from "lifi/Facets/AmarokFacet.sol";
import { console2 } from "forge-std/console2.sol";
/// @title AmarokFacetPacked
/// @author LI.FI (https://li.fi)
/// @notice Provides functionality for bridging through Amarok in a gas-optimized way
/// @custom:version 1.0.0
contract AmarokFacetPacked is ILiFi, TransferrableOwnership {
using SafeTransferLib for ERC20;
/// Storage
/// @notice The contract address of the connext handler on the source chain.
IConnextHandler private immutable connextHandler;
/// Events ///
event LiFiAmarokTransfer(bytes8 _transactionId);
/// Constructor ///
/// @notice Initialize the contract.
/// @param _connextHandler The contract address of the connext handler on the source chain.
/// @param _owner The contract owner to approve tokens.
constructor(
IConnextHandler _connextHandler,
address _owner
) TransferrableOwnership(_owner) {
connextHandler = _connextHandler;
}
/// External Methods ///
/// @dev Only meant to be called outside of the context of the diamond
/// @notice Sets approval for the Amarok bridge to spend the specified token
/// @param tokensToApprove The tokens to approve to approve to the Amarok bridge
function setApprovalForBridge(
address[] calldata tokensToApprove
) external onlyOwner {
uint256 numTokens = tokensToApprove.length;
for (uint256 i; i < numTokens; i++) {
// Give Amarok approval to bridge tokens
LibAsset.maxApproveERC20(
IERC20(tokensToApprove[i]),
address(connextHandler),
type(uint256).max
);
}
}
/// @notice Bridges ERC20 tokens via Amarok
/// No params, all data will be extracted from manually encoded callData
function startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset() external {
// extract parameters that are used multiple times in this function
address sendingAssetId = address(bytes20(msg.data[32:52]));
uint256 minAmount = uint256(uint128(bytes16(msg.data[52:68])));
address receiver = address(bytes20(msg.data[12:32]));
uint256 relayerFee = uint64(uint32(bytes4(msg.data[76:92])));
// Deposit assets
ERC20(sendingAssetId).safeTransferFrom(
msg.sender,
address(this),
minAmount
);
// call Amarok bridge
connextHandler.xcall(
uint32(bytes4(msg.data[68:72])), // _destChainDomainId
receiver, // _to
sendingAssetId,
receiver, // _delegate
minAmount - relayerFee,
uint256(uint128(uint64(uint32(bytes4(msg.data[72:76]))))), // slippageTol
"", // calldata (not required)
relayerFee
);
emit LiFiAmarokTransfer(bytes8(msg.data[4:12]));
}
function startBridgeTokensViaAmarokERC20PackedPayFeeWithNative()
external
payable
{
// extract parameters that are used multiple times in this function
address sendingAssetId = address(bytes20(msg.data[32:52]));
uint256 minAmount = uint256(uint128(bytes16(msg.data[52:68])));
address receiver = address(bytes20(msg.data[12:32]));
// Deposit assets
ERC20(sendingAssetId).safeTransferFrom(
msg.sender,
address(this),
minAmount
);
// call Amarok bridge
connextHandler.xcall{ value: msg.value }(
uint32(bytes4(msg.data[68:72])), // destChainDomainId
receiver, // _to
sendingAssetId,
receiver, // _delegate
minAmount,
uint256(uint128(uint64(uint32(bytes4(msg.data[72:76]))))), // slippageTol
"" // calldata (not required)
);
emit LiFiAmarokTransfer(bytes8(msg.data[4:12]));
}
/// @notice Bridges ERC20 tokens via Amarok
/// @param transactionId Custom transaction ID for tracking
/// @param receiver Receiving wallet address
/// @param sendingAssetId Address of the source asset to bridge
/// @param minAmount Amount of the source asset to bridge
/// @param destChainDomainId The Amarok-specific domainId of the destination chain
/// @param slippageTol Maximum acceptable slippage in BPS. For example, a value of 30 means 0.3% slippage
/// @param relayerFee The amount of relayer fee the tx called xcall with
function startBridgeTokensViaAmarokERC20MinPayFeeWithAsset(
bytes32 transactionId,
address receiver,
address sendingAssetId,
uint256 minAmount,
uint32 destChainDomainId,
uint256 slippageTol,
uint256 relayerFee
) external {
// Deposit assets
ERC20(sendingAssetId).safeTransferFrom(
msg.sender,
address(this),
minAmount
);
// Bridge assets
connextHandler.xcall(
destChainDomainId,
receiver, // _to
sendingAssetId,
receiver, // _delegate
minAmount - relayerFee,
slippageTol,
"", // calldata (not required)
relayerFee
);
emit LiFiAmarokTransfer(bytes8(transactionId));
}
/// @notice Bridges ERC20 tokens via Amarok
/// @param transactionId Custom transaction ID for tracking
/// @param receiver Receiving wallet address
/// @param sendingAssetId Address of the source asset to bridge
/// @param minAmount Amount of the source asset to bridge
/// @param destChainDomainId The Amarok-specific domainId of the destination chain
/// @param slippageTol Maximum acceptable slippage in BPS. For example, a value of 30 means 0.3% slippage
function startBridgeTokensViaAmarokERC20MinPayFeeWithNative(
bytes32 transactionId,
address receiver,
address sendingAssetId,
uint256 minAmount,
uint32 destChainDomainId,
uint256 slippageTol
) external payable {
// Deposit assets
ERC20(sendingAssetId).safeTransferFrom(
msg.sender,
address(this),
minAmount
);
// Bridge assets
connextHandler.xcall{ value: msg.value }(
destChainDomainId,
receiver, // _to
sendingAssetId,
receiver, // _delegate
minAmount,
slippageTol,
"" // calldata (not required)
);
emit LiFiAmarokTransfer(bytes8(transactionId));
}
/// @notice Encode call data to bridge ERC20 tokens via Amarok
/// @param transactionId Custom transaction ID for tracking
/// @param receiver Receiving wallet address
/// @param sendingAssetId Address of the source asset to bridge
/// @param minAmount Amount of the source asset to bridge
/// @param destChainDomainId The Amarok-specific domainId of the destination chain
/// @param slippageTol Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)
/// @param relayerFee The amount of relayer fee the tx called xcall with
function encode_startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset(
bytes32 transactionId,
address receiver,
address sendingAssetId,
uint256 minAmount,
uint32 destChainDomainId,
uint256 slippageTol,
uint256 relayerFee
) external pure returns (bytes memory) {
require(
minAmount <= type(uint128).max,
"minAmount value passed too big to fit in uint128"
);
require(
slippageTol <= type(uint32).max,
"slippageTol value passed too big to fit in uint32"
);
require(
relayerFee <= type(uint128).max,
"relayerFee value passed too big to fit in uint128"
);
return
bytes.concat(
AmarokFacetPacked
.startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset
.selector,
bytes8(transactionId), // we only use 8 bytes of the 32bytes txId in order to save gas
bytes20(receiver),
bytes20(sendingAssetId),
bytes16(uint128(minAmount)),
bytes4(destChainDomainId),
bytes4(uint32(slippageTol)),
bytes16(uint128(relayerFee))
);
}
/// @notice Encode call data to bridge ERC20 tokens via Amarok
/// @param transactionId Custom transaction ID for tracking
/// @param receiver Receiving wallet address
/// @param sendingAssetId Address of the source asset to bridge
/// @param minAmount Amount of the source asset to bridge
/// @param destChainDomainId The Amarok-specific domainId of the destination chain
/// @param slippageTol Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)
function encode_startBridgeTokensViaAmarokERC20PackedPayFeeWithNative(
bytes32 transactionId,
address receiver,
address sendingAssetId,
uint256 minAmount,
uint32 destChainDomainId,
uint256 slippageTol
) external pure returns (bytes memory) {
require(
minAmount <= type(uint128).max,
"minAmount value passed too big to fit in uint128"
);
require(
slippageTol <= type(uint32).max,
"slippageTol value passed too big to fit in uint32"
);
return
bytes.concat(
AmarokFacetPacked
.startBridgeTokensViaAmarokERC20PackedPayFeeWithNative
.selector,
bytes8(transactionId), // we only use 8 bytes of the 32bytes txId in order to save gas
bytes20(receiver),
bytes20(sendingAssetId),
bytes16(uint128(minAmount)),
bytes4(destChainDomainId),
bytes4(uint32(slippageTol))
);
}
/// @notice Decodes calldata for startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset
/// @param _data the calldata to decode
function decode_startBridgeTokensViaAmarokERC20PackedPayFeeWithAsset(
bytes calldata _data
)
external
pure
returns (BridgeData memory, AmarokFacet.AmarokData memory)
{
require(
_data.length >= 92,
"data passed in is not the correct length"
);
BridgeData memory bridgeData;
AmarokFacet.AmarokData memory amarokData;
uint32 destChainDomainId = uint32(bytes4(_data[68:72]));
bridgeData.transactionId = bytes32(bytes8(_data[4:12]));
bridgeData.receiver = address(bytes20(_data[12:32]));
bridgeData.destinationChainId = getChainIdForDomain(destChainDomainId);
bridgeData.sendingAssetId = address(bytes20(_data[32:52]));
bridgeData.minAmount = uint256(uint128(bytes16(_data[52:68])));
amarokData.callData = "";
amarokData.callTo = bridgeData.receiver;
amarokData.destChainDomainId = destChainDomainId;
amarokData.slippageTol = uint32(bytes4(_data[72:76]));
amarokData.relayerFee = uint256(uint128(bytes16(_data[76:92])));
amarokData.delegate = bridgeData.receiver;
amarokData.payFeeWithSendingAsset = true;
return (bridgeData, amarokData);
}
/// @notice Decodes calldata for startBridgeTokensViaAmarokERC20PackedPayFeeWithNative
/// @param _data the calldata to decode
function decode_startBridgeTokensViaAmarokERC20PackedPayFeeWithNative(
bytes calldata _data
)
external
pure
returns (BridgeData memory, AmarokFacet.AmarokData memory)
{
require(
_data.length >= 76,
"data passed in is not the correct length"
);
BridgeData memory bridgeData;
AmarokFacet.AmarokData memory amarokData;
uint32 destChainDomainId = uint32(bytes4(_data[68:72]));
bridgeData.transactionId = bytes32(bytes8(_data[4:12]));
bridgeData.receiver = address(bytes20(_data[12:32]));
bridgeData.destinationChainId = getChainIdForDomain(destChainDomainId);
bridgeData.sendingAssetId = address(bytes20(_data[32:52]));
bridgeData.minAmount = uint256(uint128(bytes16(_data[52:68])));
amarokData.callData = "";
amarokData.callTo = bridgeData.receiver;
amarokData.destChainDomainId = destChainDomainId;
amarokData.slippageTol = uint256(
uint128(uint32(bytes4(_data[72:76])))
);
amarokData.delegate = bridgeData.receiver;
amarokData.payFeeWithSendingAsset = false;
return (bridgeData, amarokData);
}
function getChainIdForDomain(
uint32 domainId
) public pure returns (uint32 chainId) {
if (domainId == 6648936) return 1;
// ETH
else if (domainId == 1886350457) return 137;
// POL
else if (domainId == 6450786) return 56;
// BSC
else if (domainId == 1869640809) return 10;
// OPT
else if (domainId == 6778479) return 100;
// GNO/DAI
else if (domainId == 1634886255) return 42161;
// ARB
else if (domainId == 1818848877) return 59144; // LIN
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface IConnextHandler {
/// @notice These are the call parameters that will remain constant between the
/// two chains. They are supplied on `xcall` and should be asserted on `execute`
/// @property to - The account that receives funds, in the event of a crosschain call,
/// will receive funds if the call fails.
/// @param to - The address you are sending funds (and potentially data) to
/// @param callData - The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.
/// @param originDomain - The originating domain (i.e. where `xcall` is called). Must match nomad domain schema
/// @param destinationDomain - The final domain (i.e. where `execute` / `reconcile` are called). Must match nomad domain schema
/// @param agent - An address who can execute txs on behalf of `to`, in addition to allowing relayers
/// @param recovery - The address to send funds to if your `Executor.execute call` fails
/// @param forceSlow - If true, will take slow liquidity path even if it is not a permissioned call
/// @param receiveLocal - If true, will use the local nomad asset on the destination instead of adopted.
/// @param callback - The address on the origin domain of the callback contract
/// @param callbackFee - The relayer fee to execute the callback
/// @param relayerFee - The amount of relayer fee the tx called xcall with
/// @param slippageTol - Max bps of original due to slippage (i.e. would be 9995 to tolerate .05% slippage)
struct CallParams {
address to;
bytes callData;
uint32 originDomain;
uint32 destinationDomain;
address agent;
address recovery;
bool forceSlow;
bool receiveLocal;
address callback;
uint256 callbackFee;
uint256 relayerFee;
uint256 slippageTol;
}
/// @notice The arguments you supply to the `xcall` function called by user on origin domain
/// @param params - The CallParams. These are consistent across sending and receiving chains
/// @param transactingAsset - The asset the caller sent with the transfer. Can be the adopted, canonical,
/// or the representational asset
/// @param transactingAmount - The amount of transferring asset supplied by the user in the `xcall`
/// @param originMinOut - Minimum amount received on swaps for adopted <> local on origin chain
struct XCallArgs {
CallParams params;
address transactingAsset; // Could be adopted, local, or wrapped
uint256 transactingAmount;
uint256 originMinOut;
}
function xcall(
uint32 destination,
address recipient,
address tokenAddress,
address delegate,
uint256 amount,
uint256 slippage,
bytes memory callData
) external payable returns (bytes32);
function xcall(
uint32 destination,
address recipient,
address tokenAddress,
address delegate,
uint256 amount,
uint256 slippage,
bytes memory callData,
uint256 _relayerFee
) external returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface ILiFi {
/// Structs ///
struct BridgeData {
bytes32 transactionId;
string bridge;
string integrator;
address referrer;
address sendingAssetId;
address receiver;
uint256 minAmount;
uint256 destinationChainId;
bool hasSourceSwaps;
bool hasDestinationCall;
}
/// Events ///
event LiFiTransferStarted(ILiFi.BridgeData bridgeData);
event LiFiTransferCompleted(
bytes32 indexed transactionId,
address receivingAssetId,
address receiver,
uint256 amount,
uint256 timestamp
);
event LiFiTransferRecovered(
bytes32 indexed transactionId,
address receivingAssetId,
address receiver,
uint256 amount,
uint256 timestamp
);
event LiFiGenericSwapCompleted(
bytes32 indexed transactionId,
string integrator,
string referrer,
address receiver,
address fromAssetId,
address toAssetId,
uint256 fromAmount,
uint256 toAmount
);
// Deprecated but kept here to include in ABI to parse historic events
event LiFiSwappedGeneric(
bytes32 indexed transactionId,
string integrator,
string referrer,
address fromAssetId,
address toAssetId,
uint256 fromAmount,
uint256 toAmount
);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @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.
library SafeTransferLib {
/*//////////////////////////////////////////////////////////////
ETH OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferETH(address to, uint256 amount) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Transfer the ETH and store if it succeeded or not.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "ETH_TRANSFER_FAILED");
}
/*//////////////////////////////////////////////////////////////
ERC20 OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument.
mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
require(success, "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "APPROVE_FAILED");
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;
import { InsufficientBalance, NullAddrIsNotAnERC20Token, NullAddrIsNotAValidSpender, NoTransferToNullAddress, InvalidAmount, NativeAssetTransferFailed } from "../Errors/GenericErrors.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { LibSwap } from "./LibSwap.sol";
/// @title LibAsset
/// @notice This library contains helpers for dealing with onchain transfers
/// of assets, including accounting for the native asset `assetId`
/// conventions and any noncompliant ERC20 transfers
library LibAsset {
uint256 private constant MAX_UINT = type(uint256).max;
address internal constant NULL_ADDRESS = address(0);
/// @dev All native assets use the empty address for their asset id
/// by convention
address internal constant NATIVE_ASSETID = NULL_ADDRESS; //address(0)
/// @notice Gets the balance of the inheriting contract for the given asset
/// @param assetId The asset identifier to get the balance of
/// @return Balance held by contracts using this library
function getOwnBalance(address assetId) internal view returns (uint256) {
return
isNativeAsset(assetId)
? address(this).balance
: IERC20(assetId).balanceOf(address(this));
}
/// @notice Transfers ether from the inheriting contract to a given
/// recipient
/// @param recipient Address to send ether to
/// @param amount Amount to send to given recipient
function transferNativeAsset(
address payable recipient,
uint256 amount
) private {
if (recipient == NULL_ADDRESS) revert NoTransferToNullAddress();
if (amount > address(this).balance)
revert InsufficientBalance(amount, address(this).balance);
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = recipient.call{ value: amount }("");
if (!success) revert NativeAssetTransferFailed();
}
/// @notice If the current allowance is insufficient, the allowance for a given spender
/// is set to MAX_UINT.
/// @param assetId Token address to transfer
/// @param spender Address to give spend approval to
/// @param amount Amount to approve for spending
function maxApproveERC20(
IERC20 assetId,
address spender,
uint256 amount
) internal {
if (isNativeAsset(address(assetId))) {
return;
}
if (spender == NULL_ADDRESS) {
revert NullAddrIsNotAValidSpender();
}
if (assetId.allowance(address(this), spender) < amount) {
SafeERC20.safeApprove(IERC20(assetId), spender, 0);
SafeERC20.safeApprove(IERC20(assetId), spender, MAX_UINT);
}
}
/// @notice Transfers tokens from the inheriting contract to a given
/// recipient
/// @param assetId Token address to transfer
/// @param recipient Address to send token to
/// @param amount Amount to send to given recipient
function transferERC20(
address assetId,
address recipient,
uint256 amount
) private {
if (isNativeAsset(assetId)) {
revert NullAddrIsNotAnERC20Token();
}
if (recipient == NULL_ADDRESS) {
revert NoTransferToNullAddress();
}
uint256 assetBalance = IERC20(assetId).balanceOf(address(this));
if (amount > assetBalance) {
revert InsufficientBalance(amount, assetBalance);
}
SafeERC20.safeTransfer(IERC20(assetId), recipient, amount);
}
/// @notice Transfers tokens from a sender to a given recipient
/// @param assetId Token address to transfer
/// @param from Address of sender/owner
/// @param to Address of recipient/spender
/// @param amount Amount to transfer from owner to spender
function transferFromERC20(
address assetId,
address from,
address to,
uint256 amount
) internal {
if (isNativeAsset(assetId)) {
revert NullAddrIsNotAnERC20Token();
}
if (to == NULL_ADDRESS) {
revert NoTransferToNullAddress();
}
IERC20 asset = IERC20(assetId);
uint256 prevBalance = asset.balanceOf(to);
SafeERC20.safeTransferFrom(asset, from, to, amount);
if (asset.balanceOf(to) - prevBalance != amount) {
revert InvalidAmount();
}
}
function depositAsset(address assetId, uint256 amount) internal {
if (amount == 0) revert InvalidAmount();
if (isNativeAsset(assetId)) {
if (msg.value < amount) revert InvalidAmount();
} else {
uint256 balance = IERC20(assetId).balanceOf(msg.sender);
if (balance < amount) revert InsufficientBalance(amount, balance);
transferFromERC20(assetId, msg.sender, address(this), amount);
}
}
function depositAssets(LibSwap.SwapData[] calldata swaps) internal {
for (uint256 i = 0; i < swaps.length; ) {
LibSwap.SwapData calldata swap = swaps[i];
if (swap.requiresDeposit) {
depositAsset(swap.sendingAssetId, swap.fromAmount);
}
unchecked {
i++;
}
}
}
/// @notice Determines whether the given assetId is the native asset
/// @param assetId The asset identifier to evaluate
/// @return Boolean indicating if the asset is the native asset
function isNativeAsset(address assetId) internal pure returns (bool) {
return assetId == NATIVE_ASSETID;
}
/// @notice Wrapper function to transfer a given asset (native or erc20) to
/// some recipient. Should handle all non-compliant return value
/// tokens as well by using the SafeERC20 contract by open zeppelin.
/// @param assetId Asset id for transfer (address(0) for native asset,
/// token address for erc20s)
/// @param recipient Address to send asset to
/// @param amount Amount to send to given recipient
function transferAsset(
address assetId,
address payable recipient,
uint256 amount
) internal {
isNativeAsset(assetId)
? transferNativeAsset(recipient, amount)
: transferERC20(assetId, recipient, amount);
}
/// @dev Checks whether the given address is a contract and contains code
function isContract(address _contractAddr) internal view returns (bool) {
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly {
size := extcodesize(_contractAddr)
}
return size > 0;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import { IERC173 } from "../Interfaces/IERC173.sol";
import { LibAsset } from "../Libraries/LibAsset.sol";
contract TransferrableOwnership is IERC173 {
address public owner;
address public pendingOwner;
/// Errors ///
error UnAuthorized();
error NoNullOwner();
error NewOwnerMustNotBeSelf();
error NoPendingOwnershipTransfer();
error NotPendingOwner();
/// Events ///
event OwnershipTransferRequested(
address indexed _from,
address indexed _to
);
constructor(address initialOwner) {
owner = initialOwner;
}
modifier onlyOwner() {
if (msg.sender != owner) revert UnAuthorized();
_;
}
/// @notice Initiates transfer of ownership to a new address
/// @param _newOwner the address to transfer ownership to
function transferOwnership(address _newOwner) external onlyOwner {
if (_newOwner == LibAsset.NULL_ADDRESS) revert NoNullOwner();
if (_newOwner == msg.sender) revert NewOwnerMustNotBeSelf();
pendingOwner = _newOwner;
emit OwnershipTransferRequested(msg.sender, pendingOwner);
}
/// @notice Cancel transfer of ownership
function cancelOwnershipTransfer() external onlyOwner {
if (pendingOwner == LibAsset.NULL_ADDRESS)
revert NoPendingOwnershipTransfer();
pendingOwner = LibAsset.NULL_ADDRESS;
}
/// @notice Confirms transfer of ownership to the calling address (msg.sender)
function confirmOwnershipTransfer() external {
address _pendingOwner = pendingOwner;
if (msg.sender != _pendingOwner) revert NotPendingOwner();
emit OwnershipTransferred(owner, _pendingOwner);
owner = _pendingOwner;
pendingOwner = LibAsset.NULL_ADDRESS;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import { ILiFi } from "../Interfaces/ILiFi.sol";
import { IConnextHandler } from "../Interfaces/IConnextHandler.sol";
import { LibAsset, IERC20 } from "../Libraries/LibAsset.sol";
import { ReentrancyGuard } from "../Helpers/ReentrancyGuard.sol";
import { InformationMismatch } from "../Errors/GenericErrors.sol";
import { SwapperV2, LibSwap } from "../Helpers/SwapperV2.sol";
import { Validatable } from "../Helpers/Validatable.sol";
/// @title Amarok Facet
/// @author LI.FI (https://li.fi)
/// @notice Provides functionality for bridging through Connext Amarok
/// @custom:version 2.0.0
contract AmarokFacet is ILiFi, ReentrancyGuard, SwapperV2, Validatable {
/// Storage ///
/// @notice The contract address of the connext handler on the source chain.
IConnextHandler private immutable connextHandler;
/// @param callData The data to execute on the receiving chain. If no crosschain call is needed, then leave empty.
/// @param callTo The address of the contract on dest chain that will receive bridged funds and execute data
/// @param relayerFee The amount of relayer fee the tx called xcall with
/// @param slippageTol Maximum acceptable slippage in BPS. For example, a value of 30 means 0.3% slippage
/// @param delegate Destination delegate address
/// @param destChainDomainId The Amarok-specific domainId of the destination chain
/// @param payFeeWithSendingAsset Whether to pay the relayer fee with the sending asset or not
struct AmarokData {
bytes callData;
address callTo;
uint256 relayerFee;
uint256 slippageTol;
address delegate;
uint32 destChainDomainId;
bool payFeeWithSendingAsset;
}
/// Constructor ///
/// @notice Initialize the contract.
/// @param _connextHandler The contract address of the connext handler on the source chain.
constructor(IConnextHandler _connextHandler) {
connextHandler = _connextHandler;
}
/// External Methods ///
/// @notice Bridges tokens via Amarok
/// @param _bridgeData Data containing core information for bridging
/// @param _amarokData Data specific to bridge
function startBridgeTokensViaAmarok(
BridgeData calldata _bridgeData,
AmarokData calldata _amarokData
)
external
payable
nonReentrant
refundExcessNative(payable(msg.sender))
doesNotContainSourceSwaps(_bridgeData)
validateBridgeData(_bridgeData)
noNativeAsset(_bridgeData)
{
validateDestinationCallFlag(_bridgeData, _amarokData);
LibAsset.depositAsset(
_bridgeData.sendingAssetId,
_bridgeData.minAmount
);
_startBridge(_bridgeData, _amarokData);
}
/// @notice Performs a swap before bridging via Amarok
/// @param _bridgeData The core information needed for bridging
/// @param _swapData An array of swap related data for performing swaps before bridging
/// @param _amarokData Data specific to Amarok
function swapAndStartBridgeTokensViaAmarok(
BridgeData memory _bridgeData,
LibSwap.SwapData[] calldata _swapData,
AmarokData calldata _amarokData
)
external
payable
nonReentrant
refundExcessNative(payable(msg.sender))
containsSourceSwaps(_bridgeData)
validateBridgeData(_bridgeData)
noNativeAsset(_bridgeData)
{
validateDestinationCallFlag(_bridgeData, _amarokData);
_bridgeData.minAmount = _depositAndSwap(
_bridgeData.transactionId,
_bridgeData.minAmount,
_swapData,
payable(msg.sender),
_amarokData.relayerFee
);
_startBridge(_bridgeData, _amarokData);
}
/// Private Methods ///
/// @dev Contains the business logic for the bridge via Amarok
/// @param _bridgeData The core information needed for bridging
/// @param _amarokData Data specific to Amarok
function _startBridge(
BridgeData memory _bridgeData,
AmarokData calldata _amarokData
) private {
// give max approval for token to Amarok bridge, if not already
LibAsset.maxApproveERC20(
IERC20(_bridgeData.sendingAssetId),
address(connextHandler),
_bridgeData.minAmount
);
// initiate bridge transaction
if (_amarokData.payFeeWithSendingAsset) {
connextHandler.xcall(
_amarokData.destChainDomainId,
_amarokData.callTo,
_bridgeData.sendingAssetId,
_amarokData.delegate,
_bridgeData.minAmount - _amarokData.relayerFee,
_amarokData.slippageTol,
_amarokData.callData,
_amarokData.relayerFee
);
} else {
connextHandler.xcall{ value: _amarokData.relayerFee }(
_amarokData.destChainDomainId,
_amarokData.callTo,
_bridgeData.sendingAssetId,
_amarokData.delegate,
_bridgeData.minAmount,
_amarokData.slippageTol,
_amarokData.callData
);
}
emit LiFiTransferStarted(_bridgeData);
}
function validateDestinationCallFlag(
ILiFi.BridgeData memory _bridgeData,
AmarokData calldata _amarokData
) private pure {
if (
(_amarokData.callData.length > 0) != _bridgeData.hasDestinationCall
) {
revert InformationMismatch();
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
/// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should
/// use `int256` and `uint256`. This modified version fixes that. This version is recommended
/// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in
/// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`.
/// Reference: https://github.com/NomicFoundation/hardhat/issues/2178
library console2 {
address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);
function _castLogPayloadViewToPure(
function(bytes memory) internal view fnIn
) internal pure returns (function(bytes memory) internal pure fnOut) {
assembly {
fnOut := fnIn
}
}
function _sendLogPayload(bytes memory payload) internal pure {
_castLogPayloadViewToPure(_sendLogPayloadView)(payload);
}
function _sendLogPayloadView(bytes memory payload) private view {
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE_ADDRESS;
/// @solidity memory-safe-assembly
assembly {
let payloadStart := add(payload, 32)
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
function log() internal pure {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function logUint(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function logString(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function log(int256 p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function log(string memory p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint256 p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
}
function log(uint256 p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
}
function log(uint256 p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
}
function log(uint256 p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
}
function log(string memory p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
}
function log(string memory p0, int256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1));
}
function log(string memory p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
}
function log(bool p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint256 p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
}
function log(address p0, string memory p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint256 p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
}
function log(uint256 p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
}
function log(uint256 p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
}
function log(uint256 p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
}
function log(uint256 p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
}
function log(uint256 p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
}
function log(uint256 p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
}
function log(uint256 p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
}
function log(uint256 p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
}
function log(bool p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
}
function log(bool p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
}
function log(bool p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint256 p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
}
function log(address p0, uint256 p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
}
function log(address p0, uint256 p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
}
function log(address p0, uint256 p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint256 p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, uint256 p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, string memory p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, bool p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, address p3) internal pure {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public immutable decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
// Unchecked because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}// SPDX-License-Identifier: MIT pragma solidity 0.8.17; error AlreadyInitialized(); error CannotAuthoriseSelf(); error CannotBridgeToSameNetwork(); error ContractCallNotAllowed(); error CumulativeSlippageTooHigh(uint256 minAmount, uint256 receivedAmount); error ExternalCallFailed(); error InformationMismatch(); error InsufficientBalance(uint256 required, uint256 balance); error InvalidAmount(); error InvalidCallData(); error InvalidConfig(); error InvalidContract(); error InvalidDestinationChain(); error InvalidFallbackAddress(); error InvalidReceiver(); error InvalidSendingToken(); error NativeAssetNotSupported(); error NativeAssetTransferFailed(); error NoSwapDataProvided(); error NoSwapFromZeroBalance(); error NotAContract(); error NotInitialized(); error NoTransferToNullAddress(); error NullAddrIsNotAnERC20Token(); error NullAddrIsNotAValidSpender(); error OnlyContractOwner(); error RecoveryAddressCannotBeZero(); error ReentrancyError(); error TokenNotSupported(); error UnAuthorized(); error UnsupportedChainId(uint256 chainId); error WithdrawFailed(); error ZeroAmount();
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to
* 0 before setting it to a non-zero value.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import { LibAsset } from "./LibAsset.sol";
import { LibUtil } from "./LibUtil.sol";
import { InvalidContract, NoSwapFromZeroBalance, InsufficientBalance } from "../Errors/GenericErrors.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
library LibSwap {
struct SwapData {
address callTo;
address approveTo;
address sendingAssetId;
address receivingAssetId;
uint256 fromAmount;
bytes callData;
bool requiresDeposit;
}
event AssetSwapped(
bytes32 transactionId,
address dex,
address fromAssetId,
address toAssetId,
uint256 fromAmount,
uint256 toAmount,
uint256 timestamp
);
function swap(bytes32 transactionId, SwapData calldata _swap) internal {
if (!LibAsset.isContract(_swap.callTo)) revert InvalidContract();
uint256 fromAmount = _swap.fromAmount;
if (fromAmount == 0) revert NoSwapFromZeroBalance();
uint256 nativeValue = LibAsset.isNativeAsset(_swap.sendingAssetId)
? _swap.fromAmount
: 0;
uint256 initialSendingAssetBalance = LibAsset.getOwnBalance(
_swap.sendingAssetId
);
uint256 initialReceivingAssetBalance = LibAsset.getOwnBalance(
_swap.receivingAssetId
);
if (nativeValue == 0) {
LibAsset.maxApproveERC20(
IERC20(_swap.sendingAssetId),
_swap.approveTo,
_swap.fromAmount
);
}
if (initialSendingAssetBalance < _swap.fromAmount) {
revert InsufficientBalance(
_swap.fromAmount,
initialSendingAssetBalance
);
}
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory res) = _swap.callTo.call{
value: nativeValue
}(_swap.callData);
if (!success) {
string memory reason = LibUtil.getRevertMsg(res);
revert(reason);
}
uint256 newBalance = LibAsset.getOwnBalance(_swap.receivingAssetId);
emit AssetSwapped(
transactionId,
_swap.callTo,
_swap.sendingAssetId,
_swap.receivingAssetId,
_swap.fromAmount,
newBalance > initialReceivingAssetBalance
? newBalance - initialReceivingAssetBalance
: newBalance,
block.timestamp
);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
/// @title ERC-173 Contract Ownership Standard
/// Note: the ERC-165 identifier for this interface is 0x7f5828d0
/* is ERC165 */
interface IERC173 {
/// @dev This emits when ownership of a contract changes.
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/// @notice Get the address of the owner
/// @return owner_ The address of the owner.
function owner() external view returns (address owner_);
/// @notice Set the address of the new owner of the contract
/// @dev Set _newOwner to address(0) to renounce any ownership.
/// @param _newOwner The address of the new owner of the contract
function transferOwnership(address _newOwner) external;
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;
/// @title Reentrancy Guard
/// @author LI.FI (https://li.fi)
/// @notice Abstract contract to provide protection against reentrancy
abstract contract ReentrancyGuard {
/// Storage ///
bytes32 private constant NAMESPACE = keccak256("com.lifi.reentrancyguard");
/// Types ///
struct ReentrancyStorage {
uint256 status;
}
/// Errors ///
error ReentrancyError();
/// Constants ///
uint256 private constant _NOT_ENTERED = 0;
uint256 private constant _ENTERED = 1;
/// Modifiers ///
modifier nonReentrant() {
ReentrancyStorage storage s = reentrancyStorage();
if (s.status == _ENTERED) revert ReentrancyError();
s.status = _ENTERED;
_;
s.status = _NOT_ENTERED;
}
/// Private Methods ///
/// @dev fetch local storage
function reentrancyStorage()
private
pure
returns (ReentrancyStorage storage data)
{
bytes32 position = NAMESPACE;
// solhint-disable-next-line no-inline-assembly
assembly {
data.slot := position
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import { ILiFi } from "../Interfaces/ILiFi.sol";
import { LibSwap } from "../Libraries/LibSwap.sol";
import { LibAsset } from "../Libraries/LibAsset.sol";
import { LibAllowList } from "../Libraries/LibAllowList.sol";
import { ContractCallNotAllowed, NoSwapDataProvided, CumulativeSlippageTooHigh } from "../Errors/GenericErrors.sol";
/// @title Swapper
/// @author LI.FI (https://li.fi)
/// @notice Abstract contract to provide swap functionality
contract SwapperV2 is ILiFi {
/// Types ///
/// @dev only used to get around "Stack Too Deep" errors
struct ReserveData {
bytes32 transactionId;
address payable leftoverReceiver;
uint256 nativeReserve;
}
/// Modifiers ///
/// @dev Sends any leftover balances back to the user
/// @notice Sends any leftover balances to the user
/// @param _swaps Swap data array
/// @param _leftoverReceiver Address to send leftover tokens to
/// @param _initialBalances Array of initial token balances
modifier noLeftovers(
LibSwap.SwapData[] calldata _swaps,
address payable _leftoverReceiver,
uint256[] memory _initialBalances
) {
uint256 numSwaps = _swaps.length;
if (numSwaps != 1) {
address finalAsset = _swaps[numSwaps - 1].receivingAssetId;
uint256 curBalance;
_;
for (uint256 i = 0; i < numSwaps - 1; ) {
address curAsset = _swaps[i].receivingAssetId;
// Handle multi-to-one swaps
if (curAsset != finalAsset) {
curBalance =
LibAsset.getOwnBalance(curAsset) -
_initialBalances[i];
if (curBalance > 0) {
LibAsset.transferAsset(
curAsset,
_leftoverReceiver,
curBalance
);
}
}
unchecked {
++i;
}
}
} else {
_;
}
}
/// @dev Sends any leftover balances back to the user reserving native tokens
/// @notice Sends any leftover balances to the user
/// @param _swaps Swap data array
/// @param _leftoverReceiver Address to send leftover tokens to
/// @param _initialBalances Array of initial token balances
modifier noLeftoversReserve(
LibSwap.SwapData[] calldata _swaps,
address payable _leftoverReceiver,
uint256[] memory _initialBalances,
uint256 _nativeReserve
) {
uint256 numSwaps = _swaps.length;
if (numSwaps != 1) {
address finalAsset = _swaps[numSwaps - 1].receivingAssetId;
uint256 curBalance;
_;
for (uint256 i = 0; i < numSwaps - 1; ) {
address curAsset = _swaps[i].receivingAssetId;
// Handle multi-to-one swaps
if (curAsset != finalAsset) {
curBalance =
LibAsset.getOwnBalance(curAsset) -
_initialBalances[i];
uint256 reserve = LibAsset.isNativeAsset(curAsset)
? _nativeReserve
: 0;
if (curBalance > 0) {
LibAsset.transferAsset(
curAsset,
_leftoverReceiver,
curBalance - reserve
);
}
}
unchecked {
++i;
}
}
} else {
_;
}
}
/// @dev Refunds any excess native asset sent to the contract after the main function
/// @notice Refunds any excess native asset sent to the contract after the main function
/// @param _refundReceiver Address to send refunds to
modifier refundExcessNative(address payable _refundReceiver) {
uint256 initialBalance = address(this).balance - msg.value;
_;
uint256 finalBalance = address(this).balance;
if (finalBalance > initialBalance) {
LibAsset.transferAsset(
LibAsset.NATIVE_ASSETID,
_refundReceiver,
finalBalance - initialBalance
);
}
}
/// Internal Methods ///
/// @dev Deposits value, executes swaps, and performs minimum amount check
/// @param _transactionId the transaction id associated with the operation
/// @param _minAmount the minimum amount of the final asset to receive
/// @param _swaps Array of data used to execute swaps
/// @param _leftoverReceiver The address to send leftover funds to
/// @return uint256 result of the swap
function _depositAndSwap(
bytes32 _transactionId,
uint256 _minAmount,
LibSwap.SwapData[] calldata _swaps,
address payable _leftoverReceiver
) internal returns (uint256) {
uint256 numSwaps = _swaps.length;
if (numSwaps == 0) {
revert NoSwapDataProvided();
}
address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;
uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);
if (LibAsset.isNativeAsset(finalTokenId)) {
initialBalance -= msg.value;
}
uint256[] memory initialBalances = _fetchBalances(_swaps);
LibAsset.depositAssets(_swaps);
_executeSwaps(
_transactionId,
_swaps,
_leftoverReceiver,
initialBalances
);
uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -
initialBalance;
if (newBalance < _minAmount) {
revert CumulativeSlippageTooHigh(_minAmount, newBalance);
}
return newBalance;
}
/// @dev Deposits value, executes swaps, and performs minimum amount check and reserves native token for fees
/// @param _transactionId the transaction id associated with the operation
/// @param _minAmount the minimum amount of the final asset to receive
/// @param _swaps Array of data used to execute swaps
/// @param _leftoverReceiver The address to send leftover funds to
/// @param _nativeReserve Amount of native token to prevent from being swept back to the caller
function _depositAndSwap(
bytes32 _transactionId,
uint256 _minAmount,
LibSwap.SwapData[] calldata _swaps,
address payable _leftoverReceiver,
uint256 _nativeReserve
) internal returns (uint256) {
uint256 numSwaps = _swaps.length;
if (numSwaps == 0) {
revert NoSwapDataProvided();
}
address finalTokenId = _swaps[numSwaps - 1].receivingAssetId;
uint256 initialBalance = LibAsset.getOwnBalance(finalTokenId);
if (LibAsset.isNativeAsset(finalTokenId)) {
initialBalance -= msg.value;
}
uint256[] memory initialBalances = _fetchBalances(_swaps);
LibAsset.depositAssets(_swaps);
ReserveData memory rd = ReserveData(
_transactionId,
_leftoverReceiver,
_nativeReserve
);
_executeSwaps(rd, _swaps, initialBalances);
uint256 newBalance = LibAsset.getOwnBalance(finalTokenId) -
initialBalance;
if (LibAsset.isNativeAsset(finalTokenId)) {
newBalance -= _nativeReserve;
}
if (newBalance < _minAmount) {
revert CumulativeSlippageTooHigh(_minAmount, newBalance);
}
return newBalance;
}
/// Private Methods ///
/// @dev Executes swaps and checks that DEXs used are in the allowList
/// @param _transactionId the transaction id associated with the operation
/// @param _swaps Array of data used to execute swaps
/// @param _leftoverReceiver Address to send leftover tokens to
/// @param _initialBalances Array of initial balances
function _executeSwaps(
bytes32 _transactionId,
LibSwap.SwapData[] calldata _swaps,
address payable _leftoverReceiver,
uint256[] memory _initialBalances
) internal noLeftovers(_swaps, _leftoverReceiver, _initialBalances) {
uint256 numSwaps = _swaps.length;
for (uint256 i = 0; i < numSwaps; ) {
LibSwap.SwapData calldata currentSwap = _swaps[i];
if (
!((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||
LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&
LibAllowList.contractIsAllowed(currentSwap.callTo) &&
LibAllowList.selectorIsAllowed(
bytes4(currentSwap.callData[:4])
))
) revert ContractCallNotAllowed();
LibSwap.swap(_transactionId, currentSwap);
unchecked {
++i;
}
}
}
/// @dev Executes swaps and checks that DEXs used are in the allowList
/// @param _reserveData Data passed used to reserve native tokens
/// @param _swaps Array of data used to execute swaps
function _executeSwaps(
ReserveData memory _reserveData,
LibSwap.SwapData[] calldata _swaps,
uint256[] memory _initialBalances
)
internal
noLeftoversReserve(
_swaps,
_reserveData.leftoverReceiver,
_initialBalances,
_reserveData.nativeReserve
)
{
uint256 numSwaps = _swaps.length;
for (uint256 i = 0; i < numSwaps; ) {
LibSwap.SwapData calldata currentSwap = _swaps[i];
if (
!((LibAsset.isNativeAsset(currentSwap.sendingAssetId) ||
LibAllowList.contractIsAllowed(currentSwap.approveTo)) &&
LibAllowList.contractIsAllowed(currentSwap.callTo) &&
LibAllowList.selectorIsAllowed(
bytes4(currentSwap.callData[:4])
))
) revert ContractCallNotAllowed();
LibSwap.swap(_reserveData.transactionId, currentSwap);
unchecked {
++i;
}
}
}
/// @dev Fetches balances of tokens to be swapped before swapping.
/// @param _swaps Array of data used to execute swaps
/// @return uint256[] Array of token balances.
function _fetchBalances(
LibSwap.SwapData[] calldata _swaps
) private view returns (uint256[] memory) {
uint256 numSwaps = _swaps.length;
uint256[] memory balances = new uint256[](numSwaps);
address asset;
for (uint256 i = 0; i < numSwaps; ) {
asset = _swaps[i].receivingAssetId;
balances[i] = LibAsset.getOwnBalance(asset);
if (LibAsset.isNativeAsset(asset)) {
balances[i] -= msg.value;
}
unchecked {
++i;
}
}
return balances;
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.17;
import { LibAsset } from "../Libraries/LibAsset.sol";
import { LibUtil } from "../Libraries/LibUtil.sol";
import { InvalidReceiver, InformationMismatch, InvalidSendingToken, InvalidAmount, NativeAssetNotSupported, InvalidDestinationChain, CannotBridgeToSameNetwork } from "../Errors/GenericErrors.sol";
import { ILiFi } from "../Interfaces/ILiFi.sol";
import { LibSwap } from "../Libraries/LibSwap.sol";
contract Validatable {
modifier validateBridgeData(ILiFi.BridgeData memory _bridgeData) {
if (LibUtil.isZeroAddress(_bridgeData.receiver)) {
revert InvalidReceiver();
}
if (_bridgeData.minAmount == 0) {
revert InvalidAmount();
}
if (_bridgeData.destinationChainId == block.chainid) {
revert CannotBridgeToSameNetwork();
}
_;
}
modifier noNativeAsset(ILiFi.BridgeData memory _bridgeData) {
if (LibAsset.isNativeAsset(_bridgeData.sendingAssetId)) {
revert NativeAssetNotSupported();
}
_;
}
modifier onlyAllowSourceToken(
ILiFi.BridgeData memory _bridgeData,
address _token
) {
if (_bridgeData.sendingAssetId != _token) {
revert InvalidSendingToken();
}
_;
}
modifier onlyAllowDestinationChain(
ILiFi.BridgeData memory _bridgeData,
uint256 _chainId
) {
if (_bridgeData.destinationChainId != _chainId) {
revert InvalidDestinationChain();
}
_;
}
modifier containsSourceSwaps(ILiFi.BridgeData memory _bridgeData) {
if (!_bridgeData.hasSourceSwaps) {
revert InformationMismatch();
}
_;
}
modifier doesNotContainSourceSwaps(ILiFi.BridgeData memory _bridgeData) {
if (_bridgeData.hasSourceSwaps) {
revert InformationMismatch();
}
_;
}
modifier doesNotContainDestinationCalls(
ILiFi.BridgeData memory _bridgeData
) {
if (_bridgeData.hasDestinationCall) {
revert InformationMismatch();
}
_;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import "./LibBytes.sol";
library LibUtil {
using LibBytes for bytes;
function getRevertMsg(
bytes memory _res
) internal pure returns (string memory) {
// If the _res length is less than 68, then the transaction failed silently (without a revert message)
if (_res.length < 68) return "Transaction reverted silently";
bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes
return abi.decode(revertData, (string)); // All that remains is the revert string
}
/// @notice Determines whether the given address is the zero address
/// @param addr The address to verify
/// @return Boolean indicating if the address is the zero address
function isZeroAddress(address addr) internal pure returns (bool) {
return addr == address(0);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import { InvalidContract } from "../Errors/GenericErrors.sol";
/// @title Lib Allow List
/// @author LI.FI (https://li.fi)
/// @notice Library for managing and accessing the conract address allow list
library LibAllowList {
/// Storage ///
bytes32 internal constant NAMESPACE =
keccak256("com.lifi.library.allow.list");
struct AllowListStorage {
mapping(address => bool) allowlist;
mapping(bytes4 => bool) selectorAllowList;
address[] contracts;
}
/// @dev Adds a contract address to the allow list
/// @param _contract the contract address to add
function addAllowedContract(address _contract) internal {
_checkAddress(_contract);
AllowListStorage storage als = _getStorage();
if (als.allowlist[_contract]) return;
als.allowlist[_contract] = true;
als.contracts.push(_contract);
}
/// @dev Checks whether a contract address has been added to the allow list
/// @param _contract the contract address to check
function contractIsAllowed(
address _contract
) internal view returns (bool) {
return _getStorage().allowlist[_contract];
}
/// @dev Remove a contract address from the allow list
/// @param _contract the contract address to remove
function removeAllowedContract(address _contract) internal {
AllowListStorage storage als = _getStorage();
if (!als.allowlist[_contract]) {
return;
}
als.allowlist[_contract] = false;
uint256 length = als.contracts.length;
// Find the contract in the list
for (uint256 i = 0; i < length; i++) {
if (als.contracts[i] == _contract) {
// Move the last element into the place to delete
als.contracts[i] = als.contracts[length - 1];
// Remove the last element
als.contracts.pop();
break;
}
}
}
/// @dev Fetch contract addresses from the allow list
function getAllowedContracts() internal view returns (address[] memory) {
return _getStorage().contracts;
}
/// @dev Add a selector to the allow list
/// @param _selector the selector to add
function addAllowedSelector(bytes4 _selector) internal {
_getStorage().selectorAllowList[_selector] = true;
}
/// @dev Removes a selector from the allow list
/// @param _selector the selector to remove
function removeAllowedSelector(bytes4 _selector) internal {
_getStorage().selectorAllowList[_selector] = false;
}
/// @dev Returns if selector has been added to the allow list
/// @param _selector the selector to check
function selectorIsAllowed(bytes4 _selector) internal view returns (bool) {
return _getStorage().selectorAllowList[_selector];
}
/// @dev Fetch local storage struct
function _getStorage()
internal
pure
returns (AllowListStorage storage als)
{
bytes32 position = NAMESPACE;
// solhint-disable-next-line no-inline-assembly
assembly {
als.slot := position
}
}
/// @dev Contains business logic for validating a contract address.
/// @param _contract address of the dex to check
function _checkAddress(address _contract) private view {
if (_contract == address(0)) revert InvalidContract();
if (_contract.code.length == 0) revert InvalidContract();
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
library LibBytes {
// solhint-disable no-inline-assembly
// LibBytes specific errors
error SliceOverflow();
error SliceOutOfBounds();
error AddressOutOfBounds();
bytes16 private constant _SYMBOLS = "0123456789abcdef";
// -------------------------
function slice(
bytes memory _bytes,
uint256 _start,
uint256 _length
) internal pure returns (bytes memory) {
if (_length + 31 < _length) revert SliceOverflow();
if (_bytes.length < _start + _length) revert SliceOutOfBounds();
bytes memory tempBytes;
assembly {
switch iszero(_length)
case 0 {
// Get a location of some free memory and store it in tempBytes as
// Solidity does for memory variables.
tempBytes := mload(0x40)
// The first word of the slice result is potentially a partial
// word read from the original array. To read it, we calculate
// the length of that partial word and start copying that many
// bytes into the array. The first word we copy will start with
// data we don't care about, but the last `lengthmod` bytes will
// land at the beginning of the contents of the new array. When
// we're done copying, we overwrite the full first word with
// the actual length of the slice.
let lengthmod := and(_length, 31)
// The multiplication in the next line is necessary
// because when slicing multiples of 32 bytes (lengthmod == 0)
// the following copy loop was copying the origin's length
// and then ending prematurely not copying everything it should.
let mc := add(
add(tempBytes, lengthmod),
mul(0x20, iszero(lengthmod))
)
let end := add(mc, _length)
for {
// The multiplication in the next line has the same exact purpose
// as the one above.
let cc := add(
add(
add(_bytes, lengthmod),
mul(0x20, iszero(lengthmod))
),
_start
)
} lt(mc, end) {
mc := add(mc, 0x20)
cc := add(cc, 0x20)
} {
mstore(mc, mload(cc))
}
mstore(tempBytes, _length)
//update free-memory pointer
//allocating the array padded to 32 bytes like the compiler does now
mstore(0x40, and(add(mc, 31), not(31)))
}
//if we want a zero-length slice let's just return a zero-length array
default {
tempBytes := mload(0x40)
//zero out the 32 bytes slice we are about to return
//we need to do it because Solidity does not garbage collect
mstore(tempBytes, 0)
mstore(0x40, add(tempBytes, 0x20))
}
}
return tempBytes;
}
function toAddress(
bytes memory _bytes,
uint256 _start
) internal pure returns (address) {
if (_bytes.length < _start + 20) {
revert AddressOutOfBounds();
}
address tempAddress;
assembly {
tempAddress := div(
mload(add(add(_bytes, 0x20), _start)),
0x1000000000000000000000000
)
}
return tempAddress;
}
/// Copied from OpenZeppelin's `Strings.sol` utility library.
/// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/8335676b0e99944eef6a742e16dcd9ff6e68e609/contracts/utils/Strings.sol
function toHexString(
uint256 value,
uint256 length
) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}{
"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": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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"}]Contract Creation Code
60a06040523480156200001157600080fd5b50604051620028e7380380620028e7833981016040819052620000349162000073565b600080546001600160a01b0319166001600160a01b0392831617905516608052620000b2565b6001600160a01b03811681146200007057600080fd5b50565b600080604083850312156200008757600080fd5b825162000094816200005a565b6020840151909250620000a7816200005a565b809150509250929050565b6080516127fd620000ea60003960008181610404015281816105f001528181610a0a01528181610eab015261149701526127fd6000f3fe6080604052600436106100e85760003560e01c80638da5cb5b1161008a578063e30c397811610059578063e30c39781461028c578063ecda1c0e146102b9578063f2fde38b146102c1578063f536efc6146102e157600080fd5b80638da5cb5b146101d057806390f21c80146102225780639c5647d914610237578063df0359e21461025757600080fd5b806362fcecbf116100c657806362fcecbf14610144578063698fbb561461017b57806370313c4b1461018e5780637200b829146101bb57600080fd5b806323452b9c146100ed5780633abdecb4146101045780634c47864214610124575b600080fd5b3480156100f957600080fd5b50610102610301565b005b34801561011057600080fd5b5061010261011f36600461216c565b6103cb565b34801561013057600080fd5b5061010261013f3660046121d6565b610567565b34801561015057600080fd5b5061016461015f36600461224b565b61064d565b60405161017292919061239a565b60405180910390f35b6101026101893660046124ce565b61096c565b34801561019a57600080fd5b506101ae6101a93660046124ce565b610ad8565b604051610172919061252d565b3480156101c757600080fd5b50610102610d14565b3480156101dc57600080fd5b506000546101fd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610172565b34801561022e57600080fd5b50610102610dfa565b34801561024357600080fd5b5061016461025236600461224b565b611055565b34801561026357600080fd5b50610277610272366004612547565b61134f565b60405163ffffffff9091168152602001610172565b34801561029857600080fd5b506001546101fd9073ffffffffffffffffffffffffffffffffffffffff1681565b610102611404565b3480156102cd57600080fd5b506101026102dc366004612562565b611631565b3480156102ed57600080fd5b506101ae6102fc36600461216c565b61178f565b60005473ffffffffffffffffffffffffffffffffffffffff163314610352576040517fbe24598300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015473ffffffffffffffffffffffffffffffffffffffff166103a1576040517f75cdea1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6103ed73ffffffffffffffffffffffffffffffffffffffff8616333087611a73565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166393f18ac584888881610437878b6125ac565b60405160e087901b7fffffffff0000000000000000000000000000000000000000000000000000000016815263ffffffff95909516600486015273ffffffffffffffffffffffffffffffffffffffff938416602486015291831660448501529091166064830152608482015260a4810185905261010060c4820152600061010482015260e48101849052610124016020604051808303816000875af11580156104e4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050891906125c5565b506040517fffffffffffffffff000000000000000000000000000000000000000000000000881681527fe13311fb0fe0ee03852624f65380d885625f6dd9797b55c8404d22b093c10fbd9060200160405180910390a150505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105b8576040517fbe24598300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060005b81811015610647576106358484838181106105d9576105d96125de565b90506020020160208101906105ee9190612562565b7f00000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611b39565b8061063f8161260d565b9150506105bc565b50505050565b6040805161014081018252600080825260606020808401829052838501829052818401839052608080850184905260a080860185905260c080870186905260e0808801879052610100880187905261012088018790528851908101895285815293840186905296830185905292820184905281018390529081018290529283015290605c831015610765576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f646174612070617373656420696e206973206e6f742074686520636f7272656360448201527f74206c656e67746800000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b604080516101408101825260008082526060602083018190529282018390529181018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101919091526040805160e081018252606080825260006020830181905292820183905281018290526080810182905260a0810182905260c0810191909152600061080060486044888a612645565b6108099161266f565b60e01c905061081c600c6004888a612645565b610825916126b7565b7fffffffffffffffff0000000000000000000000000000000000000000000000001683526108576020600c888a612645565b610860916126fd565b60601c60a08401526108718161134f565b63ffffffff1660e084015261088a60346020888a612645565b610893916126fd565b60601c60808401526108a960446034888a612645565b6108b291612743565b60801c60c084015260408051602080820190925260008152835260a08085015173ffffffffffffffffffffffffffffffffffffffff169184019190915263ffffffff821690830152610908604c6048888a612645565b6109119161266f565b60e01c6060830152610927605c604c888a612645565b61093091612743565b608090811c604084015260a084015173ffffffffffffffffffffffffffffffffffffffff169083015250600160c0820152909590945092505050565b61098e73ffffffffffffffffffffffffffffffffffffffff8516333086611a73565b6040517f8aac16ba00000000000000000000000000000000000000000000000000000000815263ffffffff8316600482015273ffffffffffffffffffffffffffffffffffffffff86811660248301819052868216604484015260648301526084820185905260a4820183905260e060c4830152600060e48301527f00000000000000000000000000000000000000000000000000000000000000001690638aac16ba9034906101040160206040518083038185885af1158015610a55573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610a7a91906125c5565b506040517fffffffffffffffff000000000000000000000000000000000000000000000000871681527fe13311fb0fe0ee03852624f65380d885625f6dd9797b55c8404d22b093c10fbd9060200160405180910390a1505050505050565b60606fffffffffffffffffffffffffffffffff841115610b7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f6d696e416d6f756e742076616c75652070617373656420746f6f20626967207460448201527f6f2066697420696e2075696e7431323800000000000000000000000000000000606482015260840161075c565b63ffffffff821115610c0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f736c697070616765546f6c2076616c75652070617373656420746f6f2062696760448201527f20746f2066697420696e2075696e743332000000000000000000000000000000606482015260840161075c565b50604080517fecda1c0e0000000000000000000000000000000000000000000000000000000060208201527fffffffffffffffff000000000000000000000000000000000000000000000000979097166024880152606095861b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116602c8901529490951b9093168585015260809190911b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000016605485015260e090811b7fffffffff00000000000000000000000000000000000000000000000000000000908116606486015291901b1660688301528051604c818403018152606c909201905290565b60015473ffffffffffffffffffffffffffffffffffffffff16338114610d66576040517f1853971c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055600180549091169055565b6000610e0a603460203684612645565b610e13916126fd565b60601c90506000610e28604460343684612645565b610e3191612743565b60801c90506000610e466020600c3684612645565b610e4f916126fd565b60601c90506000610e64605c604c3684612645565b610e6d9161266f565b60e01c9050610e9473ffffffffffffffffffffffffffffffffffffffff8516333086611a73565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166393f18ac5610edf60486044366000612645565b610ee89161266f565b60e01c848781610ef8878a6125ac565b610f07604c6048366000612645565b610f109161266f565b60405160e088811b7fffffffff0000000000000000000000000000000000000000000000000000000016825263ffffffff909716600482015273ffffffffffffffffffffffffffffffffffffffff958616602482015293851660448501529390911660648301526084820152911c60a482015261010060c4820152600061010482015260e48101849052610124016020604051808303816000875af1158015610fbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe191906125c5565b507fe13311fb0fe0ee03852624f65380d885625f6dd9797b55c8404d22b093c10fbd611012600c6004366000612645565b61101b916126b7565b6040517fffffffffffffffff000000000000000000000000000000000000000000000000909116815260200160405180910390a150505050565b6040805161014081018252600080825260606020808401829052838501829052818401839052608080850184905260a080860185905260c080870186905260e0808801879052610100880187905261012088018790528851908101895285815293840186905296830185905292820184905281018390529081018290529283015290604c831015611168576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f646174612070617373656420696e206973206e6f742074686520636f7272656360448201527f74206c656e677468000000000000000000000000000000000000000000000000606482015260840161075c565b604080516101408101825260008082526060602083018190529282018390529181018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101919091526040805160e081018252606080825260006020830181905292820183905281018290526080810182905260a0810182905260c0810191909152600061120360486044888a612645565b61120c9161266f565b60e01c905061121f600c6004888a612645565b611228916126b7565b7fffffffffffffffff00000000000000000000000000000000000000000000000016835261125a6020600c888a612645565b611263916126fd565b60601c60a08401526112748161134f565b63ffffffff1660e084015261128d60346020888a612645565b611296916126fd565b60601c60808401526112ac60446034888a612645565b6112b591612743565b60801c60c084015260408051602080820190925260008152835260a08085015173ffffffffffffffffffffffffffffffffffffffff169184019190915263ffffffff82169083015261130b604c6048888a612645565b6113149161266f565b60e01c60608301525060a082015173ffffffffffffffffffffffffffffffffffffffff166080820152600060c0820152909590945092505050565b60008163ffffffff16626574680361136957506001919050565b8163ffffffff1663706f6c790361138257506089919050565b8163ffffffff1662626e620361139a57506038919050565b8163ffffffff16636f707469036113b35750600a919050565b8163ffffffff1662676e6f036113cb57506064919050565b8163ffffffff16636172626f036113e5575061a4b1919050565b8163ffffffff16636c696e6d036113ff575061e708919050565b919050565b6000611414603460203684612645565b61141d916126fd565b60601c90506000611432604460343684612645565b61143b91612743565b60801c905060006114506020600c3684612645565b611459916126fd565b60601c905061148073ffffffffffffffffffffffffffffffffffffffff8416333085611a73565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016638aac16ba346114cc60486044366000612645565b6114d59161266f565b60e01c848781886114eb604c6048366000612645565b6114f49161266f565b60405160e089811b7fffffffff0000000000000000000000000000000000000000000000000000000016825263ffffffff909716600482015273ffffffffffffffffffffffffffffffffffffffff95861660248201529385166044850152939091166064830152608482015290821c60a482015260c4810191909152600060e48201526101040160206040518083038185885af1158015611599573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906115be91906125c5565b507fe13311fb0fe0ee03852624f65380d885625f6dd9797b55c8404d22b093c10fbd6115ef600c6004366000612645565b6115f8916126b7565b6040517fffffffffffffffff000000000000000000000000000000000000000000000000909116815260200160405180910390a1505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611682576040517fbe24598300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166116cf576040517f1beca37400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff82160361171e576040517fbf1ea9fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831690811790915560405133907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b60606fffffffffffffffffffffffffffffffff851115611831576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f6d696e416d6f756e742076616c75652070617373656420746f6f20626967207460448201527f6f2066697420696e2075696e7431323800000000000000000000000000000000606482015260840161075c565b63ffffffff8311156118c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f736c697070616765546f6c2076616c75652070617373656420746f6f2062696760448201527f20746f2066697420696e2075696e743332000000000000000000000000000000606482015260840161075c565b6fffffffffffffffffffffffffffffffff821115611965576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f72656c617965724665652076616c75652070617373656420746f6f206269672060448201527f746f2066697420696e2075696e74313238000000000000000000000000000000606482015260840161075c565b50604080517f90f21c800000000000000000000000000000000000000000000000000000000060208201527fffffffffffffffff0000000000000000000000000000000000000000000000009890981660248901527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606097881b8116602c8a01529590961b909416868601527fffffffffffffffffffffffffffffffff00000000000000000000000000000000608093841b811660548801527fffffffff0000000000000000000000000000000000000000000000000000000060e093841b811660648901529190921b16606886015291901b16606c8301528051808303605c018152607c909201905290565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080611b32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c4544000000000000000000000000604482015260640161075c565b5050505050565b73ffffffffffffffffffffffffffffffffffffffff8316611b5957505050565b73ffffffffffffffffffffffffffffffffffffffff8216611ba6576040517f63ba9bff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015282919085169063dd62ed3e90604401602060405180830381865afa158015611c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3f91906125c5565b1015611c7c57611c5183836000611c81565b611c7c83837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611c81565b505050565b801580611d2157506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611cfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1f91906125c5565b155b611dad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606482015260840161075c565b6040805173ffffffffffffffffffffffffffffffffffffffff848116602483015260448083018590528351808403909101815260649092018352602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490840152611c7c92869291600091611e78918516908490611f25565b9050805160001480611e99575080806020019051810190611e999190612789565b611c7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161075c565b6060611f348484600085611f3c565b949350505050565b606082471015611fce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161075c565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611ff791906127ab565b60006040518083038185875af1925050503d8060008114612034576040519150601f19603f3d011682016040523d82523d6000602084013e612039565b606091505b509150915061204a87838387612055565b979650505050505050565b606083156120eb5782516000036120e45773ffffffffffffffffffffffffffffffffffffffff85163b6120e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161075c565b5081611f34565b611f3483838151156121005781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161075c919061252d565b803573ffffffffffffffffffffffffffffffffffffffff811681146113ff57600080fd5b803563ffffffff811681146113ff57600080fd5b600080600080600080600060e0888a03121561218757600080fd5b8735965061219760208901612134565b95506121a560408901612134565b9450606088013593506121ba60808901612158565b925060a0880135915060c0880135905092959891949750929550565b600080602083850312156121e957600080fd5b823567ffffffffffffffff8082111561220157600080fd5b818501915085601f83011261221557600080fd5b81358181111561222457600080fd5b8660208260051b850101111561223957600080fd5b60209290920196919550909350505050565b6000806020838503121561225e57600080fd5b823567ffffffffffffffff8082111561227657600080fd5b818501915085601f83011261228a57600080fd5b81358181111561229957600080fd5b86602082850101111561223957600080fd5b60005b838110156122c65781810151838201526020016122ae565b50506000910152565b600081518084526122e78160208601602086016122ab565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000815160e0845261232e60e08501826122cf565b9050602083015173ffffffffffffffffffffffffffffffffffffffff80821660208701526040850151604087015260608501516060870152806080860151166080870152505063ffffffff60a08401511660a085015260c0830151151560c08501528091505092915050565b6040815282516040820152600060208401516101408060608501526123c36101808501836122cf565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08584030160808601526123fe83826122cf565b925050606086015161242860a086018273ffffffffffffffffffffffffffffffffffffffff169052565b50608086015173ffffffffffffffffffffffffffffffffffffffff811660c08601525060a086015173ffffffffffffffffffffffffffffffffffffffff811660e08601525060c0860151610100818187015260e08801519150610120828188015281890151925061249c8488018415159052565b88015180151561016088015292506124b2915050565b5082810360208401526124c58185612319565b95945050505050565b60008060008060008060c087890312156124e757600080fd5b863595506124f760208801612134565b945061250560408801612134565b93506060870135925061251a60808801612158565b915060a087013590509295509295509295565b60208152600061254060208301846122cf565b9392505050565b60006020828403121561255957600080fd5b61254082612158565b60006020828403121561257457600080fd5b61254082612134565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156125bf576125bf61257d565b92915050565b6000602082840312156125d757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361263e5761263e61257d565b5060010190565b6000808585111561265557600080fd5b8386111561266257600080fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156126af5780818660040360031b1b83161692505b505092915050565b7fffffffffffffffff00000000000000000000000000000000000000000000000081358181169160088510156126af5760089490940360031b84901b1690921692915050565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156126af5760149490940360031b84901b1690921692915050565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000081358181169160108510156126af5760109490940360031b84901b1690921692915050565b60006020828403121561279b57600080fd5b8151801515811461254057600080fd5b600082516127bd8184602087016122ab565b919091019291505056fea26469706673582212205c48a914e6c0c0306a247e84686124fef3e0e56e59a3aeccb04a2615b0ab20d964736f6c634300081100330000000000000000000000008898b472c54c31894e3b9bb83cea802a5d0e63c600000000000000000000000011f1022ca6adef6400e5677528a80d49a069c00c
Deployed Bytecode
0x6080604052600436106100e85760003560e01c80638da5cb5b1161008a578063e30c397811610059578063e30c39781461028c578063ecda1c0e146102b9578063f2fde38b146102c1578063f536efc6146102e157600080fd5b80638da5cb5b146101d057806390f21c80146102225780639c5647d914610237578063df0359e21461025757600080fd5b806362fcecbf116100c657806362fcecbf14610144578063698fbb561461017b57806370313c4b1461018e5780637200b829146101bb57600080fd5b806323452b9c146100ed5780633abdecb4146101045780634c47864214610124575b600080fd5b3480156100f957600080fd5b50610102610301565b005b34801561011057600080fd5b5061010261011f36600461216c565b6103cb565b34801561013057600080fd5b5061010261013f3660046121d6565b610567565b34801561015057600080fd5b5061016461015f36600461224b565b61064d565b60405161017292919061239a565b60405180910390f35b6101026101893660046124ce565b61096c565b34801561019a57600080fd5b506101ae6101a93660046124ce565b610ad8565b604051610172919061252d565b3480156101c757600080fd5b50610102610d14565b3480156101dc57600080fd5b506000546101fd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610172565b34801561022e57600080fd5b50610102610dfa565b34801561024357600080fd5b5061016461025236600461224b565b611055565b34801561026357600080fd5b50610277610272366004612547565b61134f565b60405163ffffffff9091168152602001610172565b34801561029857600080fd5b506001546101fd9073ffffffffffffffffffffffffffffffffffffffff1681565b610102611404565b3480156102cd57600080fd5b506101026102dc366004612562565b611631565b3480156102ed57600080fd5b506101ae6102fc36600461216c565b61178f565b60005473ffffffffffffffffffffffffffffffffffffffff163314610352576040517fbe24598300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015473ffffffffffffffffffffffffffffffffffffffff166103a1576040517f75cdea1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b6103ed73ffffffffffffffffffffffffffffffffffffffff8616333087611a73565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008898b472c54c31894e3b9bb83cea802a5d0e63c6166393f18ac584888881610437878b6125ac565b60405160e087901b7fffffffff0000000000000000000000000000000000000000000000000000000016815263ffffffff95909516600486015273ffffffffffffffffffffffffffffffffffffffff938416602486015291831660448501529091166064830152608482015260a4810185905261010060c4820152600061010482015260e48101849052610124016020604051808303816000875af11580156104e4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061050891906125c5565b506040517fffffffffffffffff000000000000000000000000000000000000000000000000881681527fe13311fb0fe0ee03852624f65380d885625f6dd9797b55c8404d22b093c10fbd9060200160405180910390a150505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105b8576040517fbe24598300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060005b81811015610647576106358484838181106105d9576105d96125de565b90506020020160208101906105ee9190612562565b7f0000000000000000000000008898b472c54c31894e3b9bb83cea802a5d0e63c67fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611b39565b8061063f8161260d565b9150506105bc565b50505050565b6040805161014081018252600080825260606020808401829052838501829052818401839052608080850184905260a080860185905260c080870186905260e0808801879052610100880187905261012088018790528851908101895285815293840186905296830185905292820184905281018390529081018290529283015290605c831015610765576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f646174612070617373656420696e206973206e6f742074686520636f7272656360448201527f74206c656e67746800000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b604080516101408101825260008082526060602083018190529282018390529181018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101919091526040805160e081018252606080825260006020830181905292820183905281018290526080810182905260a0810182905260c0810191909152600061080060486044888a612645565b6108099161266f565b60e01c905061081c600c6004888a612645565b610825916126b7565b7fffffffffffffffff0000000000000000000000000000000000000000000000001683526108576020600c888a612645565b610860916126fd565b60601c60a08401526108718161134f565b63ffffffff1660e084015261088a60346020888a612645565b610893916126fd565b60601c60808401526108a960446034888a612645565b6108b291612743565b60801c60c084015260408051602080820190925260008152835260a08085015173ffffffffffffffffffffffffffffffffffffffff169184019190915263ffffffff821690830152610908604c6048888a612645565b6109119161266f565b60e01c6060830152610927605c604c888a612645565b61093091612743565b608090811c604084015260a084015173ffffffffffffffffffffffffffffffffffffffff169083015250600160c0820152909590945092505050565b61098e73ffffffffffffffffffffffffffffffffffffffff8516333086611a73565b6040517f8aac16ba00000000000000000000000000000000000000000000000000000000815263ffffffff8316600482015273ffffffffffffffffffffffffffffffffffffffff86811660248301819052868216604484015260648301526084820185905260a4820183905260e060c4830152600060e48301527f0000000000000000000000008898b472c54c31894e3b9bb83cea802a5d0e63c61690638aac16ba9034906101040160206040518083038185885af1158015610a55573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610a7a91906125c5565b506040517fffffffffffffffff000000000000000000000000000000000000000000000000871681527fe13311fb0fe0ee03852624f65380d885625f6dd9797b55c8404d22b093c10fbd9060200160405180910390a1505050505050565b60606fffffffffffffffffffffffffffffffff841115610b7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f6d696e416d6f756e742076616c75652070617373656420746f6f20626967207460448201527f6f2066697420696e2075696e7431323800000000000000000000000000000000606482015260840161075c565b63ffffffff821115610c0e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f736c697070616765546f6c2076616c75652070617373656420746f6f2062696760448201527f20746f2066697420696e2075696e743332000000000000000000000000000000606482015260840161075c565b50604080517fecda1c0e0000000000000000000000000000000000000000000000000000000060208201527fffffffffffffffff000000000000000000000000000000000000000000000000979097166024880152606095861b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000908116602c8901529490951b9093168585015260809190911b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000016605485015260e090811b7fffffffff00000000000000000000000000000000000000000000000000000000908116606486015291901b1660688301528051604c818403018152606c909201905290565b60015473ffffffffffffffffffffffffffffffffffffffff16338114610d66576040517f1853971c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055600180549091169055565b6000610e0a603460203684612645565b610e13916126fd565b60601c90506000610e28604460343684612645565b610e3191612743565b60801c90506000610e466020600c3684612645565b610e4f916126fd565b60601c90506000610e64605c604c3684612645565b610e6d9161266f565b60e01c9050610e9473ffffffffffffffffffffffffffffffffffffffff8516333086611a73565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008898b472c54c31894e3b9bb83cea802a5d0e63c6166393f18ac5610edf60486044366000612645565b610ee89161266f565b60e01c848781610ef8878a6125ac565b610f07604c6048366000612645565b610f109161266f565b60405160e088811b7fffffffff0000000000000000000000000000000000000000000000000000000016825263ffffffff909716600482015273ffffffffffffffffffffffffffffffffffffffff958616602482015293851660448501529390911660648301526084820152911c60a482015261010060c4820152600061010482015260e48101849052610124016020604051808303816000875af1158015610fbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe191906125c5565b507fe13311fb0fe0ee03852624f65380d885625f6dd9797b55c8404d22b093c10fbd611012600c6004366000612645565b61101b916126b7565b6040517fffffffffffffffff000000000000000000000000000000000000000000000000909116815260200160405180910390a150505050565b6040805161014081018252600080825260606020808401829052838501829052818401839052608080850184905260a080860185905260c080870186905260e0808801879052610100880187905261012088018790528851908101895285815293840186905296830185905292820184905281018390529081018290529283015290604c831015611168576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f646174612070617373656420696e206973206e6f742074686520636f7272656360448201527f74206c656e677468000000000000000000000000000000000000000000000000606482015260840161075c565b604080516101408101825260008082526060602083018190529282018390529181018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101919091526040805160e081018252606080825260006020830181905292820183905281018290526080810182905260a0810182905260c0810191909152600061120360486044888a612645565b61120c9161266f565b60e01c905061121f600c6004888a612645565b611228916126b7565b7fffffffffffffffff00000000000000000000000000000000000000000000000016835261125a6020600c888a612645565b611263916126fd565b60601c60a08401526112748161134f565b63ffffffff1660e084015261128d60346020888a612645565b611296916126fd565b60601c60808401526112ac60446034888a612645565b6112b591612743565b60801c60c084015260408051602080820190925260008152835260a08085015173ffffffffffffffffffffffffffffffffffffffff169184019190915263ffffffff82169083015261130b604c6048888a612645565b6113149161266f565b60e01c60608301525060a082015173ffffffffffffffffffffffffffffffffffffffff166080820152600060c0820152909590945092505050565b60008163ffffffff16626574680361136957506001919050565b8163ffffffff1663706f6c790361138257506089919050565b8163ffffffff1662626e620361139a57506038919050565b8163ffffffff16636f707469036113b35750600a919050565b8163ffffffff1662676e6f036113cb57506064919050565b8163ffffffff16636172626f036113e5575061a4b1919050565b8163ffffffff16636c696e6d036113ff575061e708919050565b919050565b6000611414603460203684612645565b61141d916126fd565b60601c90506000611432604460343684612645565b61143b91612743565b60801c905060006114506020600c3684612645565b611459916126fd565b60601c905061148073ffffffffffffffffffffffffffffffffffffffff8416333085611a73565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008898b472c54c31894e3b9bb83cea802a5d0e63c616638aac16ba346114cc60486044366000612645565b6114d59161266f565b60e01c848781886114eb604c6048366000612645565b6114f49161266f565b60405160e089811b7fffffffff0000000000000000000000000000000000000000000000000000000016825263ffffffff909716600482015273ffffffffffffffffffffffffffffffffffffffff95861660248201529385166044850152939091166064830152608482015290821c60a482015260c4810191909152600060e48201526101040160206040518083038185885af1158015611599573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906115be91906125c5565b507fe13311fb0fe0ee03852624f65380d885625f6dd9797b55c8404d22b093c10fbd6115ef600c6004366000612645565b6115f8916126b7565b6040517fffffffffffffffff000000000000000000000000000000000000000000000000909116815260200160405180910390a1505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611682576040517fbe24598300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81166116cf576040517f1beca37400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff82160361171e576040517fbf1ea9fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831690811790915560405133907fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae127890600090a350565b60606fffffffffffffffffffffffffffffffff851115611831576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f6d696e416d6f756e742076616c75652070617373656420746f6f20626967207460448201527f6f2066697420696e2075696e7431323800000000000000000000000000000000606482015260840161075c565b63ffffffff8311156118c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f736c697070616765546f6c2076616c75652070617373656420746f6f2062696760448201527f20746f2066697420696e2075696e743332000000000000000000000000000000606482015260840161075c565b6fffffffffffffffffffffffffffffffff821115611965576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f72656c617965724665652076616c75652070617373656420746f6f206269672060448201527f746f2066697420696e2075696e74313238000000000000000000000000000000606482015260840161075c565b50604080517f90f21c800000000000000000000000000000000000000000000000000000000060208201527fffffffffffffffff0000000000000000000000000000000000000000000000009890981660248901527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606097881b8116602c8a01529590961b909416868601527fffffffffffffffffffffffffffffffff00000000000000000000000000000000608093841b811660548801527fffffffff0000000000000000000000000000000000000000000000000000000060e093841b811660648901529190921b16606886015291901b16606c8301528051808303605c018152607c909201905290565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080611b32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c4544000000000000000000000000604482015260640161075c565b5050505050565b73ffffffffffffffffffffffffffffffffffffffff8316611b5957505050565b73ffffffffffffffffffffffffffffffffffffffff8216611ba6576040517f63ba9bff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015282919085169063dd62ed3e90604401602060405180830381865afa158015611c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3f91906125c5565b1015611c7c57611c5183836000611c81565b611c7c83837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff611c81565b505050565b801580611d2157506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611cfb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1f91906125c5565b155b611dad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606482015260840161075c565b6040805173ffffffffffffffffffffffffffffffffffffffff848116602483015260448083018590528351808403909101815260649092018352602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b30000000000000000000000000000000000000000000000000000000017905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656490840152611c7c92869291600091611e78918516908490611f25565b9050805160001480611e99575080806020019051810190611e999190612789565b611c7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161075c565b6060611f348484600085611f3c565b949350505050565b606082471015611fce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161075c565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611ff791906127ab565b60006040518083038185875af1925050503d8060008114612034576040519150601f19603f3d011682016040523d82523d6000602084013e612039565b606091505b509150915061204a87838387612055565b979650505050505050565b606083156120eb5782516000036120e45773ffffffffffffffffffffffffffffffffffffffff85163b6120e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161075c565b5081611f34565b611f3483838151156121005781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161075c919061252d565b803573ffffffffffffffffffffffffffffffffffffffff811681146113ff57600080fd5b803563ffffffff811681146113ff57600080fd5b600080600080600080600060e0888a03121561218757600080fd5b8735965061219760208901612134565b95506121a560408901612134565b9450606088013593506121ba60808901612158565b925060a0880135915060c0880135905092959891949750929550565b600080602083850312156121e957600080fd5b823567ffffffffffffffff8082111561220157600080fd5b818501915085601f83011261221557600080fd5b81358181111561222457600080fd5b8660208260051b850101111561223957600080fd5b60209290920196919550909350505050565b6000806020838503121561225e57600080fd5b823567ffffffffffffffff8082111561227657600080fd5b818501915085601f83011261228a57600080fd5b81358181111561229957600080fd5b86602082850101111561223957600080fd5b60005b838110156122c65781810151838201526020016122ae565b50506000910152565b600081518084526122e78160208601602086016122ab565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000815160e0845261232e60e08501826122cf565b9050602083015173ffffffffffffffffffffffffffffffffffffffff80821660208701526040850151604087015260608501516060870152806080860151166080870152505063ffffffff60a08401511660a085015260c0830151151560c08501528091505092915050565b6040815282516040820152600060208401516101408060608501526123c36101808501836122cf565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08584030160808601526123fe83826122cf565b925050606086015161242860a086018273ffffffffffffffffffffffffffffffffffffffff169052565b50608086015173ffffffffffffffffffffffffffffffffffffffff811660c08601525060a086015173ffffffffffffffffffffffffffffffffffffffff811660e08601525060c0860151610100818187015260e08801519150610120828188015281890151925061249c8488018415159052565b88015180151561016088015292506124b2915050565b5082810360208401526124c58185612319565b95945050505050565b60008060008060008060c087890312156124e757600080fd5b863595506124f760208801612134565b945061250560408801612134565b93506060870135925061251a60808801612158565b915060a087013590509295509295509295565b60208152600061254060208301846122cf565b9392505050565b60006020828403121561255957600080fd5b61254082612158565b60006020828403121561257457600080fd5b61254082612134565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156125bf576125bf61257d565b92915050565b6000602082840312156125d757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361263e5761263e61257d565b5060010190565b6000808585111561265557600080fd5b8386111561266257600080fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156126af5780818660040360031b1b83161692505b505092915050565b7fffffffffffffffff00000000000000000000000000000000000000000000000081358181169160088510156126af5760089490940360031b84901b1690921692915050565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156126af5760149490940360031b84901b1690921692915050565b7fffffffffffffffffffffffffffffffff0000000000000000000000000000000081358181169160108510156126af5760109490940360031b84901b1690921692915050565b60006020828403121561279b57600080fd5b8151801515811461254057600080fd5b600082516127bd8184602087016122ab565b919091019291505056fea26469706673582212205c48a914e6c0c0306a247e84686124fef3e0e56e59a3aeccb04a2615b0ab20d964736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000008898b472c54c31894e3b9bb83cea802a5d0e63c600000000000000000000000011f1022ca6adef6400e5677528a80d49a069c00c
-----Decoded View---------------
Arg [0] : _connextHandler (address): 0x8898B472C54c31894e3B9bb83cEA802a5d0e63C6
Arg [1] : _owner (address): 0x11F1022cA6AdEF6400e5677528a80d49a069C00c
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000008898b472c54c31894e3b9bb83cea802a5d0e63c6
Arg [1] : 00000000000000000000000011f1022ca6adef6400e5677528a80d49a069c00c
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.