Source Code
Latest 25 from a total of 35,446 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Arbitrum Swaps | 205986447 | 642 days ago | IN | 0.00011241 ETH | 0.0000064 | ||||
| Arbitrum Swaps | 205986438 | 642 days ago | IN | 0.00011241 ETH | 0.0000064 | ||||
| Arbitrum Swaps | 205986402 | 642 days ago | IN | 0.00011241 ETH | 0.0000064 | ||||
| Arbitrum Swaps | 205985960 | 642 days ago | IN | 0.00011241 ETH | 0.00000615 | ||||
| Arbitrum Swaps | 205985867 | 642 days ago | IN | 0.00011241 ETH | 0.00000614 | ||||
| Arbitrum Swaps | 205201702 | 645 days ago | IN | 0.00011229 ETH | 0.00000587 | ||||
| Arbitrum Swaps | 205201650 | 645 days ago | IN | 0.00011229 ETH | 0.00000587 | ||||
| Arbitrum Swaps | 205201495 | 645 days ago | IN | 0.00028506 ETH | 0.00000575 | ||||
| Arbitrum Swaps | 205136263 | 645 days ago | IN | 0.00022894 ETH | 0.00000569 | ||||
| Arbitrum Swaps | 205135903 | 645 days ago | IN | 0.00022894 ETH | 0.00000571 | ||||
| Arbitrum Swaps | 204535700 | 647 days ago | IN | 0.00030621 ETH | 0.00000416 | ||||
| Arbitrum Swaps | 204289565 | 647 days ago | IN | 0.00022894 ETH | 0.00000412 | ||||
| Arbitrum Swaps | 204289299 | 647 days ago | IN | 0.00022894 ETH | 0.00000415 | ||||
| Arbitrum Swaps | 204289110 | 647 days ago | IN | 0.0001186 ETH | 0.00000413 | ||||
| Arbitrum Swaps | 203473212 | 650 days ago | IN | 0.00011181 ETH | 0.00000409 | ||||
| Arbitrum Swaps | 202917982 | 651 days ago | IN | 0.0002216 ETH | 0.00000418 | ||||
| Arbitrum Swaps | 202442042 | 653 days ago | IN | 0.0002216 ETH | 0.00000418 | ||||
| Arbitrum Swaps | 202410870 | 653 days ago | IN | 0.0001168 ETH | 0.00000428 | ||||
| Arbitrum Swaps | 201665508 | 655 days ago | IN | 0.00014014 ETH | 0.00000464 | ||||
| Arbitrum Swaps | 201665040 | 655 days ago | IN | 0.00029943 ETH | 0.00000466 | ||||
| Arbitrum Swaps | 200475819 | 659 days ago | IN | 0.00004389 ETH | 0.00000422 | ||||
| Arbitrum Swaps | 200108760 | 660 days ago | IN | 0.00004404 ETH | 0.00000441 | ||||
| Arbitrum Swaps | 200108586 | 660 days ago | IN | 0.00004404 ETH | 0.00000439 | ||||
| Arbitrum Swaps | 199659739 | 661 days ago | IN | 0.00042039 ETH | 0.00000529 | ||||
| Arbitrum Swaps | 199659648 | 661 days ago | IN | 0.00042039 ETH | 0.0000053 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 205986447 | 642 days ago | 0.00011241 ETH | ||||
| 205986438 | 642 days ago | 0.00011241 ETH | ||||
| 205986402 | 642 days ago | 0.00011241 ETH | ||||
| 205985960 | 642 days ago | 0.00011241 ETH | ||||
| 205985867 | 642 days ago | 0.00011241 ETH | ||||
| 205201702 | 645 days ago | 0.00011229 ETH | ||||
| 205201650 | 645 days ago | 0.00011229 ETH | ||||
| 205201495 | 645 days ago | 0.00028506 ETH | ||||
| 205136263 | 645 days ago | 0.00022894 ETH | ||||
| 205135903 | 645 days ago | 0.00022894 ETH | ||||
| 204535700 | 647 days ago | 0.00030621 ETH | ||||
| 204289565 | 647 days ago | 0.00022894 ETH | ||||
| 204289299 | 647 days ago | 0.00022894 ETH | ||||
| 204289110 | 647 days ago | 0.0001186 ETH | ||||
| 203473212 | 650 days ago | 0.00011181 ETH | ||||
| 202917982 | 651 days ago | 0.0002216 ETH | ||||
| 202442042 | 653 days ago | 0.0002216 ETH | ||||
| 202410870 | 653 days ago | 0.0001168 ETH | ||||
| 201665508 | 655 days ago | 0.00014014 ETH | ||||
| 201665040 | 655 days ago | 0.00029943 ETH | ||||
| 200475819 | 659 days ago | 0.00004389 ETH | ||||
| 200108760 | 660 days ago | 0.00004404 ETH | ||||
| 200108586 | 660 days ago | 0.00004404 ETH | ||||
| 199659739 | 661 days ago | 0.00042039 ETH | ||||
| 199659648 | 661 days ago | 0.00042039 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ArbitrumSwaps
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: ISC
pragma solidity 0.8.17;
import "../../adapters/UniswapAdapter.sol";
import "../../adapters/SushiAdapter.sol";
import "../../adapters/XCaliburAdapter.sol";
import "./StargateArbitrum.sol";
import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol";
import {CamelotAdapter} from "../../adapters/CamelotAdapter.sol";
import {IWETH9} from "../../interfaces/IWETH9.sol";
import {IERC20} from "openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IArbitrumSwaps} from "./interfaces/IArbitrumSwaps.sol";
contract ArbitrumSwaps is
UniswapAdapter,
SushiAdapter,
XCaliburAdapter,
StargateArbitrum,
CamelotAdapter,
IArbitrumSwaps
{
using SafeERC20 for IERC20;
error MoreThanZero();
error WithdrawFailed();
error InvaldStep();
event FeePaid(address _token, uint256 _fee);
IWETH9 internal immutable weth;
address public feeCollector;
uint8 private locked = 1;
modifier lock() {
require(locked == 1, "REENTRANCY");
locked = 2;
_;
locked = 1;
}
struct SrcTransferParams {
address token;
address receiver;
uint256 amount;
}
//Constants
uint8 internal constant BATCH_DEPOSIT = 1;
uint8 internal constant WETH_DEPOSIT = 2;
uint8 internal constant UNI_SINGLE = 3;
uint8 internal constant UNI_MULTI = 4;
uint8 internal constant SUSHI_LEGACY = 5;
uint8 internal constant XCAL = 6;
uint8 internal constant CAMELOT = 7;
uint8 internal constant WETH_WITHDRAW = 13;
uint8 internal constant SRC_TRANSFER = 14;
uint8 internal constant STARGATE = 15;
constructor(
address _weth,
ISwapRouter _swapRouter,
address _feeCollector,
address _factory,
bytes32 _pairCodeHash,
address _xcalFactory,
address _camelotRouter,
IStargateRouter _stargateRouter
)
UniswapAdapter(_swapRouter)
SushiAdapter(_factory, _pairCodeHash)
XCaliburAdapter(_xcalFactory, _weth)
CamelotAdapter(_camelotRouter)
StargateArbitrum(_stargateRouter)
{
weth = IWETH9(_weth);
feeCollector = _feeCollector;
}
///@param steps the steps taken to accomplish the necessary desired actions for the transaction. Available steps are listed above.
///@param data the necessary data that goes with each transaction.
function arbitrumSwaps(uint8[] calldata steps, bytes[] calldata data) external payable override lock {
if (steps.length != data.length) revert MismatchedLengths();
for (uint256 i; i < steps.length; i++) {
uint8 step = steps[i];
if (step == BATCH_DEPOSIT) {
(address[] memory tokens, uint256[] memory amounts) = abi.decode(data[i], (address[], uint256[]));
for (uint256 j; j < tokens.length; j++) {
if (amounts[j] <= 0) revert MoreThanZero();
IERC20(tokens[j]).safeTransferFrom(msg.sender, address(this), amounts[j]);
}
} else if (step == WETH_DEPOSIT) {
uint256 _amount = abi.decode(data[i], (uint256));
if (_amount == 0) revert MoreThanZero();
weth.deposit{value: _amount}();
} else if (step == UNI_SINGLE) {
UniswapV3Single[] memory params = abi.decode(data[i], (UniswapV3Single[]));
for (uint256 j; j < params.length; j++) {
UniswapV3Single memory swapData = params[j];
swapExactInputSingle(swapData);
}
} else if (step == UNI_MULTI) {
UniswapV3Multi[] memory params = abi.decode(data[i], (UniswapV3Multi[]));
for (uint256 j; j < params.length; j++) {
swapExactInputMultihop(params[j]);
}
} else if (step == SUSHI_LEGACY) {
SushiParams[] memory params = abi.decode(data[i], (SushiParams[]));
for (uint256 j; j < params.length; j++) {
_swapExactTokensForTokens(params[j]);
}
} else if (step == XCAL) {
XcaliburParams[] memory params = abi.decode(data[i], (XcaliburParams[]));
for (uint256 j; j < params.length; j++) {
swapExactTokensForTokens(params[j]);
}
} else if (step == CAMELOT) {
(uint256 amountIn, address[] memory path, address referrer, uint256 deadline) =
abi.decode(data[i], (uint256, address[], address, uint256));
camelotSwap(amountIn, path, referrer, deadline);
} else if (step == WETH_WITHDRAW) {
(address to, uint256 amount) = abi.decode(data[i], (address, uint256));
amount = amount != 0 ? amount : IERC20(weth).balanceOf(address(this));
weth.withdraw(amount);
uint256 ethFee = calculateFee(amount);
SafeTransferLib.safeTransferETH(to, (amount - ethFee));
SafeTransferLib.safeTransferETH(feeCollector, ethFee);
} else if (step == SRC_TRANSFER) {
SrcTransferParams[] memory params = abi.decode(data[i], (SrcTransferParams[]));
for (uint256 k; k < params.length; k++) {
_srcTransfer(params[k].token, params[k].amount, params[k].receiver);
}
} else if (step == STARGATE) {
(StargateParams memory params, uint8[] memory stepperions, bytes[] memory datass) =
abi.decode(data[i], (StargateParams, uint8[], bytes[]));
stargateSwap(params, stepperions, datass);
} else {
revert InvaldStep();
}
}
}
function _srcTransfer(address _token, uint256 amount, address to) private {
amount = amount != 0 ? amount : IERC20(_token).balanceOf(address(this));
uint256 fee = calculateFee(amount);
amount -= fee;
IERC20(_token).safeTransfer(feeCollector, fee);
IERC20(_token).safeTransfer(to, amount);
emit FeePaid(_token, fee);
}
function calculateFee(uint256 amount) internal pure returns (uint256 fee) {
fee = amount - ((amount * 9995) / 1e4);
}
receive() external payable {}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;
interface ISwapFactory {
function allPairsLength() external view returns (uint);
function isPair(address pair) external view returns (bool);
function pairCodeHash() external pure returns (bytes32);
function getPair(address tokenA, address token, bool stable) external view returns (address);
function createPair(address tokenA, address tokenB, bool stable) external returns (address pair);
function fee(bool stable) external view returns (uint);
function feeCollector() external view returns (address);
function setFeeTier(bool stable, uint fee) external;
function admin() external view returns (address);
function setAdmin(address _admin) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;
interface ISwapPair {
function transferFrom(address src, address dst, uint amount) external returns (bool);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function burn(address to) external returns (uint amount0, uint amount1);
function mint(address to) external returns (uint liquidity);
function getReserves() external view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast);
function getAmountOut(uint, address) external view returns (uint);
function claimFees() external returns (uint, uint);
function tokens() external view returns (address, address);
function claimable0(address _account) external view returns (uint);
function claimable1(address _account) external view returns (uint);
function index0() external view returns (uint);
function index1() external view returns (uint);
function balanceOf(address _account) external view returns (uint);
function approve(address _spender, uint _value) external returns (bool);
function reserve0() external view returns (uint);
function reserve1() external view returns (uint);
function current(address tokenIn, uint amountIn) external view returns (uint amountOut);
function currentCumulativePrices() external view returns (uint reserve0Cumulative, uint reserve1Cumulative, uint blockTimestamp);
function sample(address tokenIn, uint amountIn, uint points, uint window) external view returns (uint[] memory);
function quote(address tokenIn, uint amountIn, uint granularity) external view returns (uint amountOut);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;
interface IRouter {
function getAmountOut(uint amountIn, address tokenIn, address tokenOut) external view returns (uint out, bool stable);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {IERC20} from 'openzeppelin/contracts/token/ERC20/IERC20.sol';
/// @title WETH9 Interface
/// @author Ricsson W. Ngo
interface IWETH is IERC20 {
/* ===== UPDATE ===== */
function deposit() external payable;
function withdraw(uint256 amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;
library Math {
function max(uint a, uint b) internal pure returns (uint) {
return a >= b ? a : b;
}
function min(uint a, uint b) internal pure returns (uint) {
return a < b ? a : b;
}
function sqrt(uint y) internal pure returns (uint z) {
if (y > 3) {
z = y;
uint x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.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
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-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.7.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-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;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
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));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
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");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
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");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.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
* ====
*
* [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.5.11/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: 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: 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;
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;
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;
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;
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: GPL-3.0
pragma solidity >=0.5.0;
interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.12;
// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
library SafeMathUniswap {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x, "ds-math-add-overflow");
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x, "ds-math-sub-underflow");
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0;
import "sushiswap/protocols/sushiswap/contracts/interfaces/IUniswapV2Pair.sol";
import "./SafeMath.sol";
library UniswapV2Library {
using SafeMathUniswap for uint256;
// returns sorted token addresses, used to handle return values from pairs sorted in this order
function sortTokens(address tokenA, address tokenB)
internal
pure
returns (address token0, address token1)
{
require(tokenA != tokenB, "UniswapV2Library: IDENTICAL_ADDRESSES");
(token0, token1) = tokenA < tokenB
? (tokenA, tokenB)
: (tokenB, tokenA);
require(token0 != address(0), "UniswapV2Library: ZERO_ADDRESS");
}
// calculates the CREATE2 address for a pair without making any external calls
function pairFor(
address factory,
address tokenA,
address tokenB,
bytes32 pairCodeHash
) internal pure returns (address pair) {
(address token0, address token1) = sortTokens(tokenA, tokenB);
pair = address(
uint160(
uint256(
keccak256(
abi.encodePacked(
hex"ff",
factory,
keccak256(abi.encodePacked(token0, token1)),
pairCodeHash // init code hash
)
)
)
)
);
}
// fetches and sorts the reserves for a pair
function getReserves(
address factory,
address tokenA,
address tokenB,
bytes32 pairCodeHash
) internal view returns (uint256 reserveA, uint256 reserveB) {
(address token0, ) = sortTokens(tokenA, tokenB);
(uint256 reserve0, uint256 reserve1, ) = IUniswapV2Pair(
pairFor(factory, tokenA, tokenB, pairCodeHash)
).getReserves();
(reserveA, reserveB) = tokenA == token0
? (reserve0, reserve1)
: (reserve1, reserve0);
}
// given some amount of an asset and pair reserves, returns an equivalent amount of the other asset
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) internal pure returns (uint256 amountB) {
require(amountA > 0, "UniswapV2Library: INSUFFICIENT_AMOUNT");
require(
reserveA > 0 && reserveB > 0,
"UniswapV2Library: INSUFFICIENT_LIQUIDITY"
);
amountB = amountA.mul(reserveB) / reserveA;
}
// given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) internal pure returns (uint256 amountOut) {
require(amountIn > 0, "UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT");
require(
reserveIn > 0 && reserveOut > 0,
"UniswapV2Library: INSUFFICIENT_LIQUIDITY"
);
uint256 amountInWithFee = amountIn.mul(997);
uint256 numerator = amountInWithFee.mul(reserveOut);
uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);
amountOut = numerator / denominator;
}
// given an output amount of an asset and pair reserves, returns a required input amount of the other asset
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) internal pure returns (uint256 amountIn) {
require(amountOut > 0, "UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT");
require(
reserveIn > 0 && reserveOut > 0,
"UniswapV2Library: INSUFFICIENT_LIQUIDITY"
);
uint256 numerator = reserveIn.mul(amountOut).mul(1000);
uint256 denominator = reserveOut.sub(amountOut).mul(997);
amountIn = (numerator / denominator).add(1);
}
// performs chained getAmountOut calculations on any number of pairs
function getAmountsOut(
address factory,
uint256 amountIn,
address[] memory path,
bytes32 pairCodeHash
) internal view returns (uint256[] memory amounts) {
require(path.length >= 2, "UniswapV2Library: INVALID_PATH");
amounts = new uint256[](path.length);
amounts[0] = amountIn;
for (uint256 i; i < path.length - 1; i++) {
(uint256 reserveIn, uint256 reserveOut) = getReserves(
factory,
path[i],
path[i + 1],
pairCodeHash
);
amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
}
}
// performs chained getAmountIn calculations on any number of pairs
function getAmountsIn(
address factory,
uint256 amountOut,
address[] memory path,
bytes32 pairCodeHash
) internal view returns (uint256[] memory amounts) {
require(path.length >= 2, "UniswapV2Library: INVALID_PATH");
amounts = new uint256[](path.length);
amounts[amounts.length - 1] = amountOut;
for (uint256 i = path.length - 1; i > 0; i--) {
(uint256 reserveIn, uint256 reserveOut) = getReserves(
factory,
path[i - 1],
path[i],
pairCodeHash
);
amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
}
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Callback for IUniswapV3PoolActions#swap
/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface
interface IUniswapV3SwapCallback {
/// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
/// @dev In the implementation you must pay the pool tokens owed for the swap.
/// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
/// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
/// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
/// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
/// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;
import 'uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';
/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface ISwapRouter is IUniswapV3SwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another token
/// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
/// @return amountOut The amount of the received token
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another token
/// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
/// @return amountIn The amount of the input token
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.0;
import 'openzeppelin/contracts/token/ERC20/IERC20.sol';
library TransferHelper {
/// @notice Transfers tokens from the targeted address to the given destination
/// @notice Errors with 'STF' if transfer fails
/// @param token The contract address of the token to be transferred
/// @param from The originating address from which the tokens will be transferred
/// @param to The destination address of the transfer
/// @param value The amount to be transferred
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) =
token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');
}
/// @notice Transfers tokens from msg.sender to a recipient
/// @dev Errors with ST if transfer fails
/// @param token The contract address of the token which will be transferred
/// @param to The recipient of the transfer
/// @param value The value of the transfer
function safeTransfer(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');
}
/// @notice Approves the stipulated contract to spend the given allowance in the given token
/// @dev Errors with 'SA' if transfer fails
/// @param token The contract address of the token to be approved
/// @param to The target of the approval
/// @param value The amount of the given token the target will be allowed to spend
function safeApprove(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');
}
/// @notice Transfers ETH to the recipient address
/// @dev Fails with `STE`
/// @param to The destination of the transfer
/// @param value The value to be transferred
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, 'STE');
}
}//SPDX-License-Identifier: ISC
pragma solidity 0.8.17;
import {IStargateReceiver} from "../../interfaces/IStargateReceiver.sol";
import {IStargateRouter} from "../../interfaces/IStargateRouter.sol";
import {IERC20} from "openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IArbitrumSwaps} from "./interfaces/IArbitrumSwaps.sol";
import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol";
abstract contract StargateArbitrum is IStargateReceiver {
using SafeERC20 for IERC20;
/*//////////////////////////////////////////////////////////////
IMMUTABLES
//////////////////////////////////////////////////////////////*/
///@notice address of the stargate router
IStargateRouter public immutable stargateRouter;
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event ReceivedOnDestination(address indexed token, uint256 amountLD, bool failed, bool dustSent);
error NotStgRouter();
error NotEnoughGas();
error MismatchedLengths();
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(IStargateRouter _stargateRouter) {
stargateRouter = _stargateRouter;
}
///@notice struct to define parameters needed for the swap.
struct StargateParams {
uint16 dstChainId; // stargate dst chain id
address token; // token getting bridged
uint256 srcPoolId; // stargate src pool id
uint256 dstPoolId; // stargate dst pool id
uint256 amount; // amount to bridge
uint256 amountMin; // amount to bridge minimum
uint256 dustAmount; // native token to be received on dst chain
address receiver; // Mugen contract on dst chain
address to; // receiver bridge token incase of transaction reverts on dst chain
uint256 gas; // extra gas to be sent for dst chain operations
bytes32 srcContext; // random bytes32 as source context
}
/*//////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////*/
/// @param params parameters for the stargate router defined in StargateParams
/// @param stepsDst an array of steps to be performed on the dst chain
/// @param dataDst an array of data to be performed on the dst chain
function stargateSwap(StargateParams memory params, uint8[] memory stepsDst, bytes[] memory dataDst) internal {
if (stepsDst.length != dataDst.length) revert MismatchedLengths();
if (params.gas < 100000) revert NotEnoughGas();
bytes memory payload = abi.encode(params.to, stepsDst, dataDst);
params.amount = params.amount != 0 ? params.amount : IERC20(params.token).balanceOf(address(this));
if (IERC20(params.token).allowance(address(this), address(stargateRouter)) < params.amount) {
IERC20(params.token).approve(address(stargateRouter), type(uint256).max);
}
IStargateRouter(stargateRouter).swap{value: address(this).balance}(
params.dstChainId,
params.srcPoolId,
params.dstPoolId,
payable(msg.sender),
params.amount,
params.amountMin,
IStargateRouter.lzTxObj(params.gas, params.dustAmount, abi.encodePacked(params.receiver)),
abi.encodePacked(params.receiver),
payload
);
}
function getFee(StargateParams memory params, bytes memory payload) external view returns (uint256 _fee) {
bytes memory toAddress = abi.encodePacked(params.receiver);
(_fee,) = IStargateRouter(stargateRouter).quoteLayerZeroFee(
params.dstChainId,
1,
toAddress,
payload,
IStargateRouter.lzTxObj(params.gas, params.dustAmount, abi.encodePacked(params.receiver))
);
}
/*//////////////////////////////////////////////////////////////
STARGATE LOGIC
//////////////////////////////////////////////////////////////*/
/// @param _token The token contract on the local chain
/// @param amountLD The qty of local _token contract tokens
/// @param _payload The bytes containing the toAddress
function sgReceive(uint16, bytes memory, uint256, address _token, uint256 amountLD, bytes memory _payload)
external
override
{
if (msg.sender != address(stargateRouter)) revert NotStgRouter();
bool failed;
bool dustSent;
uint256 reserveGas = 100000;
uint256 limit = gasleft() - reserveGas;
(address to, uint8[] memory steps, bytes[] memory data) = abi.decode(_payload, (address, uint8[], bytes[]));
if (gasleft() < reserveGas) {
IERC20(_token).safeTransfer(to, amountLD);
/// @dev transfer any native token received as dust to the to address
if (address(this).balance > 0) {
SafeTransferLib.safeTransferETH(to, address(this).balance);
}
}
try IArbitrumSwaps(payable(address(this))).arbitrumSwaps{gas: limit}(steps, data) {}
catch (bytes memory) {
IERC20(_token).safeTransfer(to, amountLD);
failed = true;
}
if (address(this).balance > 0) {
SafeTransferLib.safeTransferETH(to, address(this).balance);
}
emit ReceivedOnDestination(_token, amountLD, failed, dustSent);
}
}//SPDX-License-Identifier: ISC
pragma solidity 0.8.17;
interface IArbitrumSwaps {
function arbitrumSwaps(uint8[] calldata, bytes[] calldata) external payable;
}//SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import {IERC20} from "openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ICamelotRouter} from "../interfaces/ICamelotRouter.sol";
abstract contract CamelotAdapter {
using SafeERC20 for IERC20;
ICamelotRouter public immutable camelotRouter;
constructor(address _camelotRouter) {
camelotRouter = ICamelotRouter(_camelotRouter);
}
function camelotSwap(uint256 amountIn, address[] memory path, address referrer, uint256 deadline) internal {
amountIn = amountIn == 0 ? IERC20(path[0]).balanceOf(address(this)) : amountIn;
if (IERC20(path[0]).allowance(address(this), address(camelotRouter)) < amountIn) {
if(IERC20(path[0]).allowance(address(this), address(camelotRouter)) > 0) {
IERC20(path[0]).safeDecreaseAllowance(address(camelotRouter), IERC20(path[0]).allowance(address(this), address(camelotRouter)));
}
IERC20(path[0]).approve(address(camelotRouter), type(uint256).max);
}
uint256[] memory amountOutMin = getAmountOut(amountIn, path);
camelotRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
amountIn, amountOutMin[amountOutMin.length - 1], path, address(this), referrer, deadline
);
}
function getAmountOut(uint256 amountIn, address[] memory path) internal view returns (uint256[] memory amounts) {
amounts = camelotRouter.getAmountsOut(amountIn, path);
}
}// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.17;
import "openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "sushiswap/protocols/sushixswap/contracts/libraries/UniswapV2Library.sol";
/// @title SushiLegacyAdapter
/// @notice Adapter for functions used to swap using Sushiswap Legacy AMM.
abstract contract SushiAdapter {
using SafeERC20 for IERC20;
/// @notice Sushiswap Legacy AMM Factory
address public factory;
/// @notice Sushiswap Legacy AMM PairCodeHash
bytes32 public pairCodeHash;
struct SushiParams {
uint256 amountIn;
uint256 amountOutMin;
address[] path;
bool sendTokens;
}
constructor(address _factory, bytes32 _pairCodeHash) {
factory = _factory;
pairCodeHash = _pairCodeHash;
}
function _swapExactTokensForTokens(SushiParams memory params) internal returns (uint256 amountOut) {
params.amountIn = params.amountIn == 0 ? IERC20(params.path[0]).balanceOf(address(this)) : params.amountIn;
uint256[] memory amounts = UniswapV2Library.getAmountsOut(factory, params.amountIn, params.path, pairCodeHash);
amountOut = amounts[amounts.length - 1];
require(amountOut >= params.amountOutMin, "insufficient-amount-out");
/// @dev force sends token to the first pair if not already sent
if (params.sendTokens) {
IERC20(params.path[0]).safeTransfer(
UniswapV2Library.pairFor(factory, params.path[0], params.path[1], pairCodeHash),
params.amountIn
);
}
_swap(amounts, params.path, address(this));
}
/// @dev requires the initial amount to have already been sent to the first pair
function _swap(uint256[] memory amounts, address[] memory path, address _to) internal virtual {
for (uint256 i; i < path.length - 1; i++) {
(address input, address output) = (path[i], path[i + 1]);
(address token0,) = UniswapV2Library.sortTokens(input, output);
uint256 amountOut = amounts[i + 1];
(uint256 amount0Out, uint256 amount1Out) =
input == token0 ? (uint256(0), amountOut) : (amountOut, uint256(0));
address to =
i < path.length - 2 ? UniswapV2Library.pairFor(factory, output, path[i + 2], pairCodeHash) : _to;
IUniswapV2Pair(UniswapV2Library.pairFor(factory, input, output, pairCodeHash)).swap(
amount0Out, amount1Out, to, new bytes(0)
);
}
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.6;
pragma abicoder v2;
import {ISwapRouter} from "uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import {TransferHelper} from "uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
import {IERC20} from "openzeppelin/contracts/token/ERC20/IERC20.sol";
abstract contract UniswapAdapter {
ISwapRouter public immutable swapRouter;
struct UniswapV3Single {
uint256 amountIn;
uint256 amountOutMin;
address token1;
address token2;
uint24 poolFee;
}
struct UniswapV3Multi {
uint256 amountIn;
uint256 amountOutMin;
address token1;
address token2;
address token3;
uint24 fee1;
uint24 fee2;
}
constructor(ISwapRouter _swapRouter) {
swapRouter = _swapRouter;
}
function swapExactInputSingle(UniswapV3Single memory swapParams) internal returns (uint256 amountOut) {
// msg.sender must approve this contract
swapParams.amountIn =
swapParams.amountIn == 0 ? IERC20(swapParams.token1).balanceOf(address(this)) : swapParams.amountIn;
// Approve the router to spend token1.
if (IERC20(swapParams.token1).allowance(address(this), address(swapRouter)) < swapParams.amountIn) {
TransferHelper.safeApprove(swapParams.token1, address(swapRouter), type(uint256).max);
}
// set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: swapParams.token1,
tokenOut: swapParams.token2,
fee: swapParams.poolFee,
recipient: address(this),
deadline: block.timestamp,
amountIn: swapParams.amountIn,
amountOutMinimum: swapParams.amountOutMin,
sqrtPriceLimitX96: 0
});
// The call to `exactInputSingle` executes the swap.
amountOut = swapRouter.exactInputSingle(params);
}
/// @dev The calling address must approve this contract to spend at least `amountIn` worth of its token1 for this function to succeed.
function swapExactInputMultihop(UniswapV3Multi memory multiParams) internal returns (uint256 amountOut) {
multiParams.amountIn =
multiParams.amountIn == 0 ? IERC20(multiParams.token1).balanceOf(address(this)) : multiParams.amountIn;
// Approve the router to spend token1.
if (IERC20(multiParams.token1).allowance(address(this), address(swapRouter)) < multiParams.amountIn) {
TransferHelper.safeApprove(multiParams.token1, address(swapRouter), type(uint256).max);
}
// Multiple pool swaps are encoded through bytes called a `path`. A path is a sequence of token addresses and poolFees that define the pools used in the swaps.
// The format for pool encoding is (tokenIn, fee, tokenOut/tokenIn, fee, tokenOut) where tokenIn/tokenOut parameter is the shared token across the pools.
ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({
path: abi.encodePacked(
multiParams.token1, multiParams.fee1, multiParams.token2, multiParams.fee2, multiParams.token3
),
recipient: address(this),
deadline: block.timestamp,
amountIn: multiParams.amountIn,
amountOutMinimum: multiParams.amountOutMin
});
// Executes the swap.
amountOut = swapRouter.exactInput(params);
}
}//SPDX-License-Identifier: ISC
pragma solidity 0.8.17;
import "3xcaliswap/contracts/periphery/interfaces/IRouter.sol";
import "3xcaliswap/contracts/core/interfaces/ISwapFactory.sol";
import "3xcaliswap/contracts/periphery/interfaces/IWETH.sol";
import "openzeppelin/contracts/token/ERC20/IERC20.sol";
import "3xcaliswap/contracts/periphery/libraries/Math.sol";
import "3xcaliswap/contracts/core/interfaces/ISwapPair.sol";
import {SafeERC20} from "openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
abstract contract XCaliburAdapter is IRouter {
using SafeERC20 for IERC20;
struct XcaliburParams {
uint256 amountIn;
uint256 amountOutMin;
route[] routes;
uint256 deadline;
}
struct route {
address from;
address to;
bool stable;
}
address public immutable xcalFactory;
IWETH public immutable xcalWeth;
uint256 internal constant MINIMUM_LIQUIDITY = 10 ** 3;
bytes32 immutable xcalPairCodeHash;
address internal constant xcalRouter = address(0x8e72bf5A45F800E182362bDF906DFB13d5D5cb5d);
modifier ensure(uint256 deadline) {
require(deadline >= block.timestamp, "BaseV1Router: EXPIRED");
_;
}
constructor(address _factory, address _xcalWeth) {
require(_factory != address(0) && _xcalWeth != address(0), "Router: zero address provided in constructor");
xcalFactory = _factory;
xcalPairCodeHash = ISwapFactory(_factory).pairCodeHash();
xcalWeth = IWETH(_xcalWeth);
}
function sortTokens(address tokenA, address tokenB) public pure returns (address token0, address token1) {
require(tokenA != tokenB, "BaseV1Router: IDENTICAL_ADDRESSES");
(token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0), "BaseV1Router: ZERO_ADDRESS");
}
// calculates the CREATE2 address for a pair without making any external calls
function pairFor(address tokenA, address tokenB, bool stable) public view returns (address pair) {
(address token0, address token1) = sortTokens(tokenA, tokenB);
pair = address(
uint160(
uint256(
keccak256(
abi.encodePacked(
hex"ff",
xcalFactory,
keccak256(abi.encodePacked(token0, token1, stable)),
xcalPairCodeHash // init code hash
)
)
)
)
);
}
// performs chained getAmountOut calculations on any number of pairs
function getAmountOut(uint256 amountIn, address tokenIn, address tokenOut)
external
view
returns (uint256 amount, bool stable)
{
address pair = pairFor(tokenIn, tokenOut, true);
uint256 amountStable;
uint256 amountVolatile;
if (ISwapFactory(xcalFactory).isPair(pair)) {
amountStable = ISwapPair(pair).getAmountOut(amountIn, tokenIn);
}
pair = pairFor(tokenIn, tokenOut, false);
if (ISwapFactory(xcalFactory).isPair(pair)) {
amountVolatile = ISwapPair(pair).getAmountOut(amountIn, tokenIn);
}
return amountStable > amountVolatile ? (amountStable, true) : (amountVolatile, false);
}
// performs chained getAmountOut calculations on any number of pairs
function getAmountsOut(uint256 amountIn, route[] memory routes) public view returns (uint256[] memory amounts) {
require(routes.length >= 1, "BaseV1Router: INVALID_PATH");
amounts = new uint[](routes.length+1);
amounts[0] = amountIn;
for (uint256 i = 0; i < routes.length; i++) {
address pair = pairFor(routes[i].from, routes[i].to, routes[i].stable);
if (ISwapFactory(xcalFactory).isPair(pair)) {
amounts[i + 1] = ISwapPair(pair).getAmountOut(amounts[i], routes[i].from);
}
}
}
function isPair(address pair) external view returns (bool) {
return ISwapFactory(xcalFactory).isPair(pair);
}
// **** SWAP ****
// requires the initial amount to have already been sent to the first pair
function _swap(uint256[] memory amounts, route[] memory routes, address _to) internal virtual {
for (uint256 i = 0; i < routes.length; i++) {
(address token0,) = sortTokens(routes[i].from, routes[i].to);
uint256 amountOut = amounts[i + 1];
(uint256 amount0Out, uint256 amount1Out) =
routes[i].from == token0 ? (uint256(0), amountOut) : (amountOut, uint256(0));
address to =
i < routes.length - 1 ? pairFor(routes[i + 1].from, routes[i + 1].to, routes[i + 1].stable) : _to;
ISwapPair(pairFor(routes[i].from, routes[i].to, routes[i].stable)).swap(
amount0Out, amount1Out, to, new bytes(0)
);
}
}
function swapExactTokensForTokens(XcaliburParams memory params)
internal
ensure(params.deadline)
returns (uint256[] memory amounts)
{
params.amountIn = params.amountIn == 0 ? IERC20(params.routes[0].from).balanceOf(address(this)) : params.amountIn;
amounts = getAmountsOut(params.amountIn, params.routes);
require(amounts[amounts.length - 1] >= params.amountOutMin, "BaseV1Router: INSUFFICIENT_OUTPUT_AMOUNT");
_safeTransfer(
params.routes[0].from,
pairFor(params.routes[0].from, params.routes[0].to, params.routes[0].stable),
amounts[0]
);
_swap(amounts, params.routes, address(this));
}
function _safeTransfer(address token, address to, uint256 value) internal {
require(token.code.length > 0);
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))));
}
function _safeTransferFrom(address token, address from, address to, uint256 value) internal {
require(token.code.length > 0);
(bool success, bytes memory data) =
token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))));
}
}//SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface ICamelotRouter {
function getPair(address token1, address token2) external view returns (address);
// **** SWAP ****
// **** SWAP (supporting fee-on-transfer tokens) ****
// requires the initial amount to have already been sent to the first pair
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
address referrer,
uint256 deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
address referrer,
uint256 deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
address referrer,
uint256 deadline
) external;
// **** LIBRARY FUNCTIONS ****
// given some amount of an asset and pair reserves, returns the quote of the other asset's reserve ratio
function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) external pure returns (uint256 amountB);
function getAmountsOut(uint256 amountIn, address[] calldata path)
external
view
returns (uint256[] memory amounts);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.7.6;
interface IStargateReceiver {
function sgReceive(
uint16 _srcChainId, // the remote chainId sending the tokens
bytes memory _srcAddress, // the remote Bridge address
uint256 _nonce,
address _token, // the token contract on the local chain
uint256 amountLD, // the qty of local _token contract tokens
bytes memory payload
) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.7.6;
pragma abicoder v2;
interface IStargateRouter {
struct lzTxObj {
uint256 dstGasForCall;
uint256 dstNativeAmount;
bytes dstNativeAddr;
}
function addLiquidity(uint256 _poolId, uint256 _amountLD, address _to) external;
function swap(
uint16 _dstChainId,
uint256 _srcPoolId,
uint256 _dstPoolId,
address payable _refundAddress,
uint256 _amountLD,
uint256 _minAmountLD,
lzTxObj memory _lzTxParams,
bytes calldata _to,
bytes calldata _payload
) external payable;
function redeemRemote(
uint16 _dstChainId,
uint256 _srcPoolId,
uint256 _dstPoolId,
address payable _refundAddress,
uint256 _amountLP,
uint256 _minAmountLD,
bytes calldata _to,
lzTxObj memory _lzTxParams
) external payable;
function instantRedeemLocal(uint16 _srcPoolId, uint256 _amountLP, address _to) external returns (uint256);
function redeemLocal(
uint16 _dstChainId,
uint256 _srcPoolId,
uint256 _dstPoolId,
address payable _refundAddress,
uint256 _amountLP,
bytes calldata _to,
lzTxObj memory _lzTxParams
) external payable;
function sendCredits(uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress)
external
payable;
function quoteLayerZeroFee(
uint16 _dstChainId,
uint8 _functionType,
bytes calldata _toAddress,
bytes calldata _transferAndCallPayload,
lzTxObj memory _lzTxParams
) external view returns (uint256, uint256);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.13;
import "openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title Interface for WETH9
interface IWETH9 is IERC20 {
/// @notice Deposit ether to get wrapped ether
function deposit() external payable;
/// @notice Withdraw wrapped ether to get ether
function withdraw(uint256) external;
}{
"remappings": [
"3xcaliSwap/=lib/3xcaliSwap/contracts/",
"3xcaliswap/=lib/3xcaliswap/",
"@core/=lib/3xcaliSwap/contracts/core/",
"@openzeppelin/=lib/3xcaliSwap/node_modules/@openzeppelin/",
"@solmate/=lib/3xcaliSwap/node_modules/solmate/src/",
"LayerZero/=lib/contracts/lib/LayerZero/contracts/",
"chainlink/=lib/chainlink/",
"contracts/=lib/contracts/contracts/",
"create3-factory/=lib/create3-factory/src/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"fraxlend/=lib/fraxlend/",
"joe-v2/=lib/joe-v2/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
"openzeppelin/=lib/openzeppelin-contracts/",
"pancake-smart-contracts/=lib/pancake-smart-contracts/",
"pancake/=lib/pancake-smart-contracts/",
"solmate/=lib/solmate/",
"spookyswap-core/=lib/spookyswap-core/contracts/",
"spookyswap/=lib/spookyswap-core/",
"sushiswap/=lib/sushiswap/",
"traderjoe/=lib/joe-v2/src/",
"uniswap/v3-core/=lib/v3-core/",
"uniswap/v3-periphery/=lib/v3-periphery/",
"utils/=lib/contracts/test/utils/",
"v3-core/=lib/v3-core/",
"v3-periphery/=lib/v3-periphery/contracts/",
"velodrome/=lib/contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"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":"address","name":"_weth","type":"address"},{"internalType":"contract ISwapRouter","name":"_swapRouter","type":"address"},{"internalType":"address","name":"_feeCollector","type":"address"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"bytes32","name":"_pairCodeHash","type":"bytes32"},{"internalType":"address","name":"_xcalFactory","type":"address"},{"internalType":"address","name":"_camelotRouter","type":"address"},{"internalType":"contract IStargateRouter","name":"_stargateRouter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvaldStep","type":"error"},{"inputs":[],"name":"MismatchedLengths","type":"error"},{"inputs":[],"name":"MoreThanZero","type":"error"},{"inputs":[],"name":"NotEnoughGas","type":"error"},{"inputs":[],"name":"NotStgRouter","type":"error"},{"inputs":[],"name":"WithdrawFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_token","type":"address"},{"indexed":false,"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"FeePaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountLD","type":"uint256"},{"indexed":false,"internalType":"bool","name":"failed","type":"bool"},{"indexed":false,"internalType":"bool","name":"dustSent","type":"bool"}],"name":"ReceivedOnDestination","type":"event"},{"inputs":[{"internalType":"uint8[]","name":"steps","type":"uint8[]"},{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"arbitrumSwaps","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"camelotRouter","outputs":[{"internalType":"contract ICamelotRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"stable","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"internalType":"struct XCaliburAdapter.route[]","name":"routes","type":"tuple[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"dstChainId","type":"uint16"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"srcPoolId","type":"uint256"},{"internalType":"uint256","name":"dstPoolId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"amountMin","type":"uint256"},{"internalType":"uint256","name":"dustAmount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"bytes32","name":"srcContext","type":"bytes32"}],"internalType":"struct StargateArbitrum.StargateParams","name":"params","type":"tuple"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"getFee","outputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"isPair","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pairCodeHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"name":"pairFor","outputs":[{"internalType":"address","name":"pair","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"sgReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"name":"sortTokens","outputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"stargateRouter","outputs":[{"internalType":"contract IStargateRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapRouter","outputs":[{"internalType":"contract ISwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xcalFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xcalWeth","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6101606040526002805460ff60a01b1916600160a01b1790553480156200002557600080fd5b506040516200520a3803806200520a8339810160408190526200004891620001cd565b6001600160a01b03878116608052600080546001600160a01b03191687831617905560018590558290829085908b908216158015906200009057506001600160a01b03811615155b620000f65760405162461bcd60e51b815260206004820152602c60248201527f526f757465723a207a65726f20616464726573732070726f766964656420696e60448201526b1031b7b739ba393ab1ba37b960a11b606482015260840160405180910390fd5b6001600160a01b03821660a081905260408051631355724960e31b81529051639aab9248916004808201926020929091908290030181865afa15801562000141573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000167919062000282565b60e0526001600160a01b0390811660c052918216610100525090811661012052978816610140525050600280546001600160a01b0319169490961693909317909455506200029c92505050565b6001600160a01b0381168114620001ca57600080fd5b50565b600080600080600080600080610100898b031215620001eb57600080fd5b8851620001f881620001b4565b60208a01519098506200020b81620001b4565b60408a01519097506200021e81620001b4565b60608a01519096506200023181620001b4565b60808a015160a08b015191965094506200024b81620001b4565b60c08a01519093506200025e81620001b4565b60e08a01519092506200027181620001b4565b809150509295985092959890939650565b6000602082840312156200029557600080fd5b5051919050565b60805160a05160c05160e051610100516101205161014051614e64620003a6600039600081816108a201528181610bf10152610c8401526000818161036b0152818161200a015281816120bb015281816121430152818161218e015281816122730152818161230301526132a50152600081816102a3015281816103e8015281816113990152818161266a015281816126f501526127770152600061054b0152600061022c0152600081816101480152818161051001528181610eb001528181610fc40152818161122201526115680152600081816102f7015281816116fa01528181611773015281816118550152818161197b015281816119f40152611acd0152614e646000f3fe6080604052600436106100f75760003560e01c80639aab92481161008a578063c415b95c11610059578063c415b95c14610319578063c45a015514610339578063e5700fd414610359578063e5e31b131461038d57600080fd5b80639aab92481461027b578063a9e56f3c14610291578063ab8236f3146102c5578063c31c9c07146102e557600080fd5b80635b676ff3116100c65780635b676ff3146101d05780635e1e6325146101e5578063750a1d481461021a5780639881fcb41461024e57600080fd5b80634285f6e4146101035780634588b7c5146101365780634c1ee03e14610182578063544caa56146101a257600080fd5b366100fe57005b600080fd5b34801561010f57600080fd5b5061012361011e366004613a97565b6103bd565b6040519081526020015b60405180910390f35b34801561014257600080fd5b5061016a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161012d565b34801561018e57600080fd5b5061016a61019d366004613af5565b6104ce565b3480156101ae57600080fd5b506101c26101bd366004613b40565b61059e565b60405161012d929190613b79565b6101e36101de366004613bd7565b610696565b005b3480156101f157600080fd5b50610205610200366004613c42565b610e78565b6040805192835290151560208301520161012d565b34801561022657600080fd5b5061016a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561025a57600080fd5b5061026e610269366004613d4b565b6110cc565b60405161012d9190613d87565b34801561028757600080fd5b5061012360015481565b34801561029d57600080fd5b5061016a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156102d157600080fd5b506101e36102e0366004613dcb565b61138e565b3480156102f157600080fd5b5061016a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561032557600080fd5b5060025461016a906001600160a01b031681565b34801561034557600080fd5b5060005461016a906001600160a01b031681565b34801561036557600080fd5b5061016a7f000000000000000000000000000000000000000000000000000000000000000081565b34801561039957600080fd5b506103ad6103a8366004613e65565b611546565b604051901515815260200161012d565b6000808360e001516040516020016103d59190613e82565b60405160208183030381529060405290507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316630a51236985600001516001848760405180606001604052808b610120015181526020018b60c0015181526020018b60e001516040516020016104539190613e82565b6040516020818303038152906040528152506040518663ffffffff1660e01b8152600401610485959493929190613f13565b6040805180830381865afa1580156104a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c59190613f6b565b50949350505050565b60008060006104dd868661059e565b6040516001600160601b0319606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000000000000000000000000000000000000000000090604901604051602081830303815290604052805190602001207f000000000000000000000000000000000000000000000000000000000000000060405160200161057c93929190613f8f565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b0316036106115760405162461bcd60e51b815260206004820152602160248201527f426173655631526f757465723a204944454e544943414c5f41444452455353456044820152605360f81b60648201526084015b60405180910390fd5b826001600160a01b0316846001600160a01b031610610631578284610634565b83835b90925090506001600160a01b03821661068f5760405162461bcd60e51b815260206004820152601a60248201527f426173655631526f757465723a205a45524f5f414444524553530000000000006044820152606401610608565b9250929050565b600254600160a01b900460ff166001146106df5760405162461bcd60e51b815260206004820152600a6024820152695245454e5452414e435960b01b6044820152606401610608565b6002805460ff60a01b1916600160a11b179055808314610712576040516373f8993760e11b815260040160405180910390fd5b60005b83811015610e5e57600085858381811061073157610731613fc2565b90506020020160208101906107469190613fe7565b905060001960ff82160161083e5760008085858581811061076957610769613fc2565b905060200281019061077b9190614004565b81019061078891906140b9565b9150915060005b82518110156108365760008282815181106107ac576107ac613fc2565b6020026020010151116107d25760405163fe4155c760e01b815260040160405180910390fd5b61082433308484815181106107e9576107e9613fc2565b602002602001015186858151811061080357610803613fc2565b60200260200101516001600160a01b03166115db909392919063ffffffff16565b8061082e81614189565b91505061078f565b505050610e4b565b60011960ff82160161091a57600084848481811061085e5761085e613fc2565b90506020028101906108709190614004565b81019061087d91906141a2565b9050806000036108a05760405163fe4155c760e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108fb57600080fd5b505af115801561090f573d6000803e3d6000fd5b505050505050610e4b565b60021960ff8216016109aa57600084848481811061093a5761093a613fc2565b905060200281019061094c9190614004565b81019061095991906141ce565b905060005b81518110156109a357600082828151811061097b5761097b613fc2565b6020026020010151905061098e8161164c565b5050808061099b90614189565b91505061095e565b5050610e4b565b60031960ff821601610a2c5760008484848181106109ca576109ca613fc2565b90506020028101906109dc9190614004565b8101906109e991906142b8565b905060005b81518110156109a357610a19828281518110610a0c57610a0c613fc2565b60200260200101516118cd565b5080610a2481614189565b9150506109ee565b60041960ff821601610aae576000848484818110610a4c57610a4c613fc2565b9050602002810190610a5e9190614004565b810190610a6b91906143ba565b905060005b81518110156109a357610a9b828281518110610a8e57610a8e613fc2565b6020026020010151611b17565b5080610aa681614189565b915050610a70565b60051960ff821601610b30576000848484818110610ace57610ace613fc2565b9050602002810190610ae09190614004565b810190610aed91906144c7565b905060005b81518110156109a357610b1d828281518110610b1057610b10613fc2565b6020026020010151611d0b565b5080610b2881614189565b915050610af2565b60061960ff821601610b9057600080600080878787818110610b5457610b54613fc2565b9050602002810190610b669190614004565b810190610b7391906145c1565b9350935093509350610b8784848484611f48565b50505050610e4b565b600c1960ff821601610d1e57600080858585818110610bb157610bb1613fc2565b9050602002810190610bc39190614004565b810190610bd09190614621565b9150915080600003610c69576040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610c40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c64919061464d565b610c6b565b805b604051632e1a7d4d60e01b8152600481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015610cd057600080fd5b505af1158015610ce4573d6000803e3d6000fd5b505050506000610cf3826123b6565b9050610d0883610d038385614666565b6123db565b600254610836906001600160a01b0316826123db565b600d1960ff821601610ddf576000848484818110610d3e57610d3e613fc2565b9050602002810190610d509190614004565b810190610d5d9190614679565b905060005b81518110156109a357610dcd828281518110610d8057610d80613fc2565b602002602001015160000151838381518110610d9e57610d9e613fc2565b602002602001015160400151848481518110610dbc57610dbc613fc2565b602002602001015160200151612431565b80610dd781614189565b915050610d62565b600e1960ff821601610e32576000806000868686818110610e0257610e02613fc2565b9050602002810190610e149190614004565b810190610e2191906147bb565b92509250925061083683838361253a565b6040516379df70e560e11b815260040160405180910390fd5b5080610e5681614189565b915050610715565b50506002805460ff60a01b1916600160a01b179055505050565b6000806000610e89858560016104ce565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa158015610ef9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1d9190614893565b15610f96576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015610f6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f93919061464d565b91505b610fa2878760006104ce565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561100d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110319190614893565b156110aa576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611083573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a7919061464d565b90505b8082116110b9578060006110bd565b8160015b94509450505050935093915050565b60606001825110156111205760405162461bcd60e51b815260206004820152601a60248201527f426173655631526f757465723a20494e56414c49445f504154480000000000006044820152606401610608565b815161112d9060016148b0565b6001600160401b038111156111445761114461383d565b60405190808252806020026020018201604052801561116d578160200160208202803683370190505b509050828160008151811061118457611184613fc2565b60200260200101818152505060005b82518110156113875760006112008483815181106111b3576111b3613fc2565b6020026020010151600001518584815181106111d1576111d1613fc2565b6020026020010151602001518685815181106111ef576111ef613fc2565b6020026020010151604001516104ce565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa15801561126b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128f9190614893565b1561137457806001600160a01b031663f140a35a8484815181106112b5576112b5613fc2565b60200260200101518685815181106112cf576112cf613fc2565b6020026020010151600001516040518363ffffffff1660e01b815260040161130a9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611327573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134b919061464d565b836113578460016148b0565b8151811061136757611367613fc2565b6020026020010181815250505b508061137f81614189565b915050611193565b5092915050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146113d757604051638afe477f60e01b815260040160405180910390fd5b600080620186a081815a6113eb9190614666565b9050600080600087806020019051810190611406919061497e565b925092509250845a1015611438576114286001600160a01b038b16848b612868565b47156114385761143883476123db565b604051635b676ff360e01b81523090635b676ff390869061145f9086908690600401614adf565b600060405180830381600088803b15801561147957600080fd5b5087f19350505050801561148b575060015b6114d9573d8080156114b9576040519150601f19603f3d011682016040523d82523d6000602084013e6114be565b606091505b506114d36001600160a01b038c16858c612868565b60019750505b47156114e9576114e983476123db565b604080518a815288151560208201528715158183015290516001600160a01b038c16917f7f345d6da48bd1339fd428ff45265a0f01258b14ca09dcf8db0c469f4f732fd3919081900360600190a250505050505050505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e5e31b1390602401602060405180830381865afa1580156115b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d59190614893565b92915050565b6040516001600160a01b03808516602483015283166044820152606481018290526116469085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612898565b50505050565b80516000901561165d5781516116cb565b60408083015190516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156116a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cb919061464d565b8083526040808401519051636eb1769f60e11b81526001600160a01b039091169063dd62ed3e906117229030907f000000000000000000000000000000000000000000000000000000000000000090600401613b79565b602060405180830381865afa15801561173f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611763919061464d565b101561179a5761179a82604001517f000000000000000000000000000000000000000000000000000000000000000060001961296a565b6040805161010081018252838201516001600160a01b0390811682526060808601518216602080850191825260808089015162ffffff90811687890190815230958801958652429288019283528a5160a08901908152938b015160c08901908152600060e08a01908152995163414bf38960e01b8152895189166004820152955188166024870152905190911660448501529351851660648401525160848301525160a4820152905160c48201529251811660e484015290917f00000000000000000000000000000000000000000000000000000000000000009091169063414bf38990610104015b6020604051808303816000875af11580156118a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c6919061464d565b9392505050565b8051600090156118de57815161194c565b60408083015190516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194c919061464d565b8083526040808401519051636eb1769f60e11b81526001600160a01b039091169063dd62ed3e906119a39030907f000000000000000000000000000000000000000000000000000000000000000090600401613b79565b602060405180830381865afa1580156119c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e4919061464d565b1015611a1b57611a1b82604001517f000000000000000000000000000000000000000000000000000000000000000060001961296a565b6040805160a08082018352918401519184015160608086015160c08088015160808901516001600160601b031997851b8816928701929092526001600160e81b031960e895861b811660d488015292841b871660d787015290931b1660eb8401521b90911660ee8201526000908061010281016040516020818303038152906040528152602001306001600160a01b0316815260200142815260200184600001518152602001846020015181525090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c04b8d59826040518263ffffffff1660e01b81526004016118839190614b0d565b805160009015611b28578151611bb3565b8160400151600081518110611b3f57611b3f613fc2565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611b8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb3919061464d565b8083526000805460408501516001549293611bdc936001600160a01b0390931692909190612a6a565b90508060018251611bed9190614666565b81518110611bfd57611bfd613fc2565b602002602001015191508260200151821015611c5b5760405162461bcd60e51b815260206004820152601760248201527f696e73756666696369656e742d616d6f756e742d6f75740000000000000000006044820152606401610608565b826060015115611cf6576000805460408501518051611cf693611cbe936001600160a01b03169291611c8f57611c8f613fc2565b60200260200101518660400151600181518110611cae57611cae613fc2565b6020026020010151600154612bed565b845160408601518051600090611cd657611cd6613fc2565b60200260200101516001600160a01b03166128689092919063ffffffff16565b611d0581846040015130612c73565b50919050565b6060816060015142811015611d5a5760405162461bcd60e51b815260206004820152601560248201527410985cd9558c549bdd5d195c8e8811561412549151605a1b6044820152606401610608565b825115611d68578251611df4565b8260400151600081518110611d7f57611d7f613fc2565b6020908102919091010151516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611dd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df4919061464d565b8084526040840151611e0691906110cc565b915082602001518260018451611e1c9190614666565b81518110611e2c57611e2c613fc2565b60200260200101511015611e935760405162461bcd60e51b815260206004820152602860248201527f426173655631526f757465723a20494e53554646494349454e545f4f555450556044820152671517d05353d5539560c21b6064820152608401610608565b611f398360400151600081518110611ead57611ead613fc2565b602002602001015160000151611f198560400151600081518110611ed357611ed3613fc2565b6020026020010151600001518660400151600081518110611ef657611ef6613fc2565b60200260200101516020015187604001516000815181106111ef576111ef613fc2565b84600081518110611f2c57611f2c613fc2565b6020026020010151612e4a565b611d0582846040015130612f32565b8315611f545783611fdb565b82600081518110611f6757611f67613fc2565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fdb919061464d565b93508383600081518110611ff157611ff1613fc2565b60200260200101516001600160a01b031663dd62ed3e307f00000000000000000000000000000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401612046929190613b79565b602060405180830381865afa158015612063573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612087919061464d565b10156122f3576000836000815181106120a2576120a2613fc2565b60200260200101516001600160a01b031663dd62ed3e307f00000000000000000000000000000000000000000000000000000000000000006040518363ffffffff1660e01b81526004016120f7929190613b79565b602060405180830381865afa158015612114573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612138919061464d565b111561223e5761223e7f00000000000000000000000000000000000000000000000000000000000000008460008151811061217557612175613fc2565b60200260200101516001600160a01b031663dd62ed3e307f00000000000000000000000000000000000000000000000000000000000000006040518363ffffffff1660e01b81526004016121ca929190613b79565b602060405180830381865afa1580156121e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220b919061464d565b8560008151811061221e5761221e613fc2565b60200260200101516001600160a01b03166131819092919063ffffffff16565b8260008151811061225157612251613fc2565b602090810291909101015160405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af11580156122cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f19190614893565b505b60006122ff858561328b565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ac3893ba8683600185516123409190614666565b8151811061235057612350613fc2565b6020026020010151873088886040518763ffffffff1660e01b815260040161237d96959493929190614b9e565b600060405180830381600087803b15801561239757600080fd5b505af11580156123ab573d6000803e3d6000fd5b505050505050505050565b60006127106123c78361270b614be2565b6123d19190614bf9565b6115d59083614666565b600080600080600085875af190508061242c5760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b6044820152606401610608565b505050565b816000036124a6576040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa15801561247d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a1919061464d565b6124a8565b815b915060006124b5836123b6565b90506124c18184614666565b6002549093506124de906001600160a01b03868116911683612868565b6124f26001600160a01b0385168385612868565b604080516001600160a01b0386168152602081018390527f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f910160405180910390a150505050565b805182511461255c576040516373f8993760e11b815260040160405180910390fd5b620186a0836101200151101561258557604051636eb14fc360e11b815260040160405180910390fd5b600083610100015183836040516020016125a193929190614c1b565b604051602081830303815290604052905083608001516000036126315760208401516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015612608573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262c919061464d565b612637565b83608001515b608085018190526020850151604051636eb1769f60e11b81526001600160a01b039091169063dd62ed3e906126929030907f000000000000000000000000000000000000000000000000000000000000000090600401613b79565b602060405180830381865afa1580156126af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d3919061464d565b101561277557602084015160405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af115801561274f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127739190614893565b505b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639fbf10fc47866000015187604001518860600151338a608001518b60a0015160405180606001604052808e610120015181526020018e60c0015181526020018e60e001516040516020016127f49190613e82565b6040516020818303038152906040528152508d60e0015160405160200161281b9190613e82565b6040516020818303038152906040528b6040518b63ffffffff1660e01b815260040161284f99989796959493929190614c5b565b6000604051808303818588803b15801561239757600080fd5b6040516001600160a01b03831660248201526044810182905261242c90849063a9059cbb60e01b9060640161160f565b60006128ed826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166133219092919063ffffffff16565b80519091501561242c578080602001905181019061290b9190614893565b61242c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610608565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916129c69190614cd8565b6000604051808303816000865af19150503d8060008114612a03576040519150601f19603f3d011682016040523d82523d6000602084013e612a08565b606091505b5091509150818015612a32575080511580612a32575080806020019051810190612a329190614893565b612a635760405162461bcd60e51b8152602060048201526002602482015261534160f01b6044820152606401610608565b5050505050565b6060600283511015612abe5760405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a20494e56414c49445f5041544800006044820152606401610608565b82516001600160401b03811115612ad757612ad761383d565b604051908082528060200260200182016040528015612b00578160200160208202803683370190505b5090508381600081518110612b1757612b17613fc2565b60200260200101818152505060005b60018451612b349190614666565b8110156104c557600080612b8888878581518110612b5457612b54613fc2565b602002602001015188866001612b6a91906148b0565b81518110612b7a57612b7a613fc2565b602002602001015188613338565b91509150612bb0848481518110612ba157612ba1613fc2565b60200260200101518383613404565b84612bbc8560016148b0565b81518110612bcc57612bcc613fc2565b60200260200101818152505050508080612be590614189565b915050612b26565b6000806000612bfc8686613523565b6040516001600160601b0319606084811b8216602084015283901b166034820152919350915087906048016040516020818303038152906040528051906020012085604051602001612c5093929190613f8f565b60408051601f198184030181529190528051602090910120979650505050505050565b60005b60018351612c849190614666565b81101561164657600080848381518110612ca057612ca0613fc2565b602002602001015185846001612cb691906148b0565b81518110612cc657612cc6613fc2565b6020026020010151915091506000612cde8383613523565b509050600087612cef8660016148b0565b81518110612cff57612cff613fc2565b60200260200101519050600080836001600160a01b0316866001600160a01b031614612d2d57826000612d31565b6000835b91509150600060028a51612d459190614666565b8810612d515788612d7e565b600054612d7e906001600160a01b0316878c612d6e8c60026148b0565b81518110611cae57611cae613fc2565b9050612da160008054906101000a90046001600160a01b03168888600154612bed565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f191660200182016040528015612dde576020820181803683370190505b506040518563ffffffff1660e01b8152600401612dfe9493929190614cf4565b600060405180830381600087803b158015612e1857600080fd5b505af1158015612e2c573d6000803e3d6000fd5b50505050505050505050508080612e4290614189565b915050612c76565b6000836001600160a01b03163b11612e6157600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612ebd9190614cd8565b6000604051808303816000865af19150503d8060008114612efa576040519150601f19603f3d011682016040523d82523d6000602084013e612eff565b606091505b5091509150818015612f29575080511580612f29575080806020019051810190612f299190614893565b612a6357600080fd5b60005b8251811015611646576000612f84848381518110612f5557612f55613fc2565b602002602001015160000151858481518110612f7357612f73613fc2565b60200260200101516020015161059e565b509050600085612f958460016148b0565b81518110612fa557612fa5613fc2565b60200260200101519050600080836001600160a01b0316878681518110612fce57612fce613fc2565b6020026020010151600001516001600160a01b031614612ff057826000612ff4565b6000835b915091506000600188516130089190614666565b86106130145786613087565b613087886130238860016148b0565b8151811061303357613033613fc2565b6020026020010151600001518988600161304d91906148b0565b8151811061305d5761305d613fc2565b6020026020010151602001518a89600161307791906148b0565b815181106111ef576111ef613fc2565b90506130da88878151811061309e5761309e613fc2565b6020026020010151600001518988815181106130bc576130bc613fc2565b6020026020010151602001518a89815181106111ef576111ef613fc2565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f191660200182016040528015613117576020820181803683370190505b506040518563ffffffff1660e01b81526004016131379493929190614cf4565b600060405180830381600087803b15801561315157600080fd5b505af1158015613165573d6000803e3d6000fd5b505050505050505050808061317990614189565b915050612f35565b604051636eb1769f60e11b81526000906001600160a01b0385169063dd62ed3e906131b29030908790600401613b79565b602060405180830381865afa1580156131cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f3919061464d565b9050818110156132575760405162461bcd60e51b815260206004820152602960248201527f5361666545524332303a2064656372656173656420616c6c6f77616e63652062604482015268656c6f77207a65726f60b81b6064820152608401610608565b6040516001600160a01b03841660248201528282036044820181905290612a6390869063095ea7b360e01b9060640161160f565b60405163d06ca61f60e01b81526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d06ca61f906132dc9086908690600401614d21565b600060405180830381865afa1580156132f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526118c69190810190614d3a565b60606133308484600085613613565b949350505050565b60008060006133478686613523565b50905060008061335989898989612bed565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015613396573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133ba9190614dd6565b506001600160701b031691506001600160701b03169150826001600160a01b0316886001600160a01b0316146133f15780826133f4565b81815b909a909950975050505050505050565b60008084116134695760405162461bcd60e51b815260206004820152602b60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4960448201526a1394155517d05353d5539560aa1b6064820152608401610608565b6000831180156134795750600082115b6134d65760405162461bcd60e51b815260206004820152602860248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4c604482015267495155494449545960c01b6064820152608401610608565b60006134e4856103e56136e3565b905060006134f282856136e3565b9050600061350c83613506886103e86136e3565b9061374a565b90506135188183614bf9565b979650505050505050565b600080826001600160a01b0316846001600160a01b0316036135955760405162461bcd60e51b815260206004820152602560248201527f556e697377617056324c6962726172793a204944454e544943414c5f41444452604482015264455353455360d81b6064820152608401610608565b826001600160a01b0316846001600160a01b0316106135b55782846135b8565b83835b90925090506001600160a01b03821661068f5760405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a205a45524f5f4144445245535300006044820152606401610608565b6060824710156136745760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610608565b600080866001600160a01b031685876040516136909190614cd8565b60006040518083038185875af1925050503d80600081146136cd576040519150601f19603f3d011682016040523d82523d6000602084013e6136d2565b606091505b50915091506135188783838761379f565b6000811580613707575082826136f98183614be2565b92506137059083614bf9565b145b6115d55760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b6044820152606401610608565b60008261375783826148b0565b91508110156115d55760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b6044820152606401610608565b6060831561380e578251600003613807576001600160a01b0385163b6138075760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610608565b5081613330565b61333083838151156138235781518083602001fd5b8060405162461bcd60e51b81526004016106089190614e1b565b634e487b7160e01b600052604160045260246000fd5b60405161016081016001600160401b03811182821017156138765761387661383d565b60405290565b604051606081016001600160401b03811182821017156138765761387661383d565b60405160a081016001600160401b03811182821017156138765761387661383d565b60405160e081016001600160401b03811182821017156138765761387661383d565b604051608081016001600160401b03811182821017156138765761387661383d565b604051601f8201601f191681016001600160401b038111828210171561392c5761392c61383d565b604052919050565b803561ffff8116811461394657600080fd5b919050565b6001600160a01b038116811461396057600080fd5b50565b80356139468161394b565b6000610160828403121561398157600080fd5b613989613853565b905061399482613934565b81526139a260208301613963565b602082015260408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013560c08201526139e560e08301613963565b60e08201526101006139f8818401613963565b9082015261012082810135908201526101409182013591810191909152919050565b60006001600160401b03821115613a3357613a3361383d565b50601f01601f191660200190565b600082601f830112613a5257600080fd5b8135613a65613a6082613a1a565b613904565b818152846020838601011115613a7a57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806101808385031215613aab57600080fd5b613ab5848461396e565b91506101608301356001600160401b03811115613ad157600080fd5b613add85828601613a41565b9150509250929050565b801515811461396057600080fd5b600080600060608486031215613b0a57600080fd5b8335613b158161394b565b92506020840135613b258161394b565b91506040840135613b3581613ae7565b809150509250925092565b60008060408385031215613b5357600080fd5b8235613b5e8161394b565b91506020830135613b6e8161394b565b809150509250929050565b6001600160a01b0392831681529116602082015260400190565b60008083601f840112613ba557600080fd5b5081356001600160401b03811115613bbc57600080fd5b6020830191508360208260051b850101111561068f57600080fd5b60008060008060408587031215613bed57600080fd5b84356001600160401b0380821115613c0457600080fd5b613c1088838901613b93565b90965094506020870135915080821115613c2957600080fd5b50613c3687828801613b93565b95989497509550505050565b600080600060608486031215613c5757600080fd5b833592506020840135613c698161394b565b91506040840135613b358161394b565b60006001600160401b03821115613c9257613c9261383d565b5060051b60200190565b600082601f830112613cad57600080fd5b81356020613cbd613a6083613c79565b82815260609283028501820192828201919087851115613cdc57600080fd5b8387015b85811015613d3e5781818a031215613cf85760008081fd5b613d0061387c565b8135613d0b8161394b565b815281860135613d1a8161394b565b81870152604082810135613d2d81613ae7565b908201528452928401928101613ce0565b5090979650505050505050565b60008060408385031215613d5e57600080fd5b8235915060208301356001600160401b03811115613d7b57600080fd5b613add85828601613c9c565b6020808252825182820181905260009190848201906040850190845b81811015613dbf57835183529284019291840191600101613da3565b50909695505050505050565b60008060008060008060c08789031215613de457600080fd5b613ded87613934565b955060208701356001600160401b0380821115613e0957600080fd5b613e158a838b01613a41565b96506040890135955060608901359150613e2e8261394b565b9093506080880135925060a08801359080821115613e4b57600080fd5b50613e5889828a01613a41565b9150509295509295509295565b600060208284031215613e7757600080fd5b81356118c68161394b565b60609190911b6001600160601b031916815260140190565b60005b83811015613eb5578181015183820152602001613e9d565b50506000910152565b60008151808452613ed6816020860160208601613e9a565b601f01601f19169290920160200192915050565b805182526020810151602083015260006040820151606060408501526133306060850182613ebe565b61ffff8616815260ff8516602082015260a060408201526000613f3960a0830186613ebe565b8281036060840152613f4b8186613ebe565b90508281036080840152613f5f8185613eea565b98975050505050505050565b60008060408385031215613f7e57600080fd5b505080516020909101519092909150565b6001600160f81b0319815260609390931b6001600160601b03191660018401526015830191909152603582015260550190565b634e487b7160e01b600052603260045260246000fd5b60ff8116811461396057600080fd5b600060208284031215613ff957600080fd5b81356118c681613fd8565b6000808335601e1984360301811261401b57600080fd5b8301803591506001600160401b0382111561403557600080fd5b60200191503681900382131561068f57600080fd5b600082601f83011261405b57600080fd5b8135602061406b613a6083613c79565b82815260059290921b8401810191818101908684111561408a57600080fd5b8286015b848110156140ae5780356140a18161394b565b835291830191830161408e565b509695505050505050565b600080604083850312156140cc57600080fd5b82356001600160401b03808211156140e357600080fd5b6140ef8683870161404a565b935060209150818501358181111561410657600080fd5b85019050601f8101861361411957600080fd5b8035614127613a6082613c79565b81815260059190911b8201830190838101908883111561414657600080fd5b928401925b828410156141645783358252928401929084019061414b565b80955050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b60006001820161419b5761419b614173565b5060010190565b6000602082840312156141b457600080fd5b5035919050565b803562ffffff8116811461394657600080fd5b600060208083850312156141e157600080fd5b82356001600160401b038111156141f757600080fd5b8301601f8101851361420857600080fd5b8035614216613a6082613c79565b81815260a0918202830184019184820191908884111561423557600080fd5b938501935b838510156142ac5780858a0312156142525760008081fd5b61425a61389e565b8535815286860135878201526040808701356142758161394b565b908201526060868101356142888161394b565b9082015260806142998782016141bb565b908201528352938401939185019161423a565b50979650505050505050565b600060208083850312156142cb57600080fd5b82356001600160401b038111156142e157600080fd5b8301601f810185136142f257600080fd5b8035614300613a6082613c79565b81815260e0918202830184019184820191908884111561431f57600080fd5b938501935b838510156142ac5780858a03121561433c5760008081fd5b6143446138c0565b85358152868601358782015260408087013561435f8161394b565b908201526060868101356143728161394b565b908201526080868101356143858161394b565b9082015260a06143968782016141bb565b9082015260c06143a78782016141bb565b9082015283529384019391850191614324565b600060208083850312156143cd57600080fd5b82356001600160401b03808211156143e457600080fd5b818501915085601f8301126143f857600080fd5b8135614406613a6082613c79565b81815260059190911b8301840190848101908883111561442557600080fd5b8585015b838110156144ba5780358581111561444057600080fd5b86016080818c03601f190112156144575760008081fd5b61445f6138e2565b8882013581526040808301358a830152606080840135898111156144835760008081fd5b6144918f8d8388010161404a565b8385015250608084013593506144a684613ae7565b820192909252845250918601918601614429565b5098975050505050505050565b600060208083850312156144da57600080fd5b82356001600160401b03808211156144f157600080fd5b818501915085601f83011261450557600080fd5b8135614513613a6082613c79565b81815260059190911b8301840190848101908883111561453257600080fd5b8585015b838110156144ba5780358581111561454d57600080fd5b86016080818c03601f190112156145645760008081fd5b61456c6138e2565b8882013581526040808301358a830152606080840135898111156145905760008081fd5b61459e8f8d83880101613c9c565b928401929092526080939093013592820192909252845250918601918601614536565b600080600080608085870312156145d757600080fd5b8435935060208501356001600160401b038111156145f457600080fd5b6146008782880161404a565b93505060408501356146118161394b565b9396929550929360600135925050565b6000806040838503121561463457600080fd5b823561463f8161394b565b946020939093013593505050565b60006020828403121561465f57600080fd5b5051919050565b818103818111156115d5576115d5614173565b6000602080838503121561468c57600080fd5b82356001600160401b038111156146a257600080fd5b8301601f810185136146b357600080fd5b80356146c1613a6082613c79565b818152606091820283018401918482019190888411156146e057600080fd5b938501935b838510156142ac5780858a0312156146fd5760008081fd5b61470561387c565b85356147108161394b565b81528587013561471f8161394b565b8188015260408681013590820152835293840193918501916146e5565b600082601f83011261474d57600080fd5b8135602061475d613a6083613c79565b82815260059290921b8401810191818101908684111561477c57600080fd5b8286015b848110156140ae5780356001600160401b0381111561479f5760008081fd5b6147ad8986838b0101613a41565b845250918301918301614780565b60008060006101a084860312156147d157600080fd5b6147db858561396e565b92506101608401356001600160401b03808211156147f857600080fd5b818601915086601f83011261480c57600080fd5b8135602061481c613a6083613c79565b82815260059290921b8401810191818101908a84111561483b57600080fd5b948201945b8386101561486257853561485381613fd8565b82529482019490820190614840565b965050505061018086013591508082111561487c57600080fd5b506148898682870161473c565b9150509250925092565b6000602082840312156148a557600080fd5b81516118c681613ae7565b808201808211156115d5576115d5614173565b600082601f8301126148d457600080fd5b815160206148e4613a6083613c79565b82815260059290921b8401810191818101908684111561490357600080fd5b8286015b848110156140ae5780516001600160401b038111156149265760008081fd5b8701603f810189136149385760008081fd5b84810151604061494a613a6083613a1a565b8281528b8284860101111561495f5760008081fd5b61496e83898301848701613e9a565b8652505050918301918301614907565b60008060006060848603121561499357600080fd5b835161499e8161394b565b809350506020808501516001600160401b03808211156149bd57600080fd5b818701915087601f8301126149d157600080fd5b81516149df613a6082613c79565b81815260059190911b8301840190848101908a8311156149fe57600080fd5b938501935b82851015614a25578451614a1681613fd8565b82529385019390850190614a03565b60408a01519097509450505080831115614a3e57600080fd5b5050614889868287016148c3565b600081518084526020808501945080840160005b83811015614a7f57815160ff1687529582019590820190600101614a60565b509495945050505050565b600081518084526020808501808196508360051b8101915082860160005b85811015614ad2578284038952614ac0848351613ebe565b98850198935090840190600101614aa8565b5091979650505050505050565b604081526000614af26040830185614a4c565b8281036020840152614b048185614a8a565b95945050505050565b602081526000825160a06020840152614b2960c0840182613ebe565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b600081518084526020808501945080840160005b83811015614a7f5781516001600160a01b031687529582019590820190600101614b79565b86815285602082015260c060408201526000614bbd60c0830187614b65565b6001600160a01b03958616606084015293909416608082015260a00152949350505050565b80820281158282048414176115d5576115d5614173565b600082614c1657634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0384168152606060208201819052600090614c3f90830185614a4c565b8281036040840152614c518185614a8a565b9695505050505050565b600061012061ffff8c1683528a602084015289604084015260018060a01b03891660608401528760808401528660a08401528060c0840152614c9f81840187613eea565b905082810360e0840152614cb38186613ebe565b9050828103610100840152614cc88185613ebe565b9c9b505050505050505050505050565b60008251614cea818460208701613e9a565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000614c516080830184613ebe565b8281526040602082015260006133306040830184614b65565b60006020808385031215614d4d57600080fd5b82516001600160401b03811115614d6357600080fd5b8301601f81018513614d7457600080fd5b8051614d82613a6082613c79565b81815260059190911b82018301908381019087831115614da157600080fd5b928401925b8284101561351857835182529284019290840190614da6565b80516001600160701b038116811461394657600080fd5b600080600060608486031215614deb57600080fd5b614df484614dbf565b9250614e0260208501614dbf565b9150604084015163ffffffff81168114613b3557600080fd5b6020815260006118c66020830184613ebe56fea2646970667358221220545f4b54ff83e127a1f3592a25603d126e070df8f5d0aadced82f2cd4eb8381b64736f6c6343000811003300000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000b09f29e2ba229fdb2bb68dd0e2049a76c014ac8a000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4e18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303000000000000000000000000d158bd9e8b6efd3ca76830b66715aa2b7bad2218000000000000000000000000c873fecbd354f5a56e00e710b90ef4201db2448d00000000000000000000000053bf833a5d6c4dda888f69c22c88c9f356a41614
Deployed Bytecode
0x6080604052600436106100f75760003560e01c80639aab92481161008a578063c415b95c11610059578063c415b95c14610319578063c45a015514610339578063e5700fd414610359578063e5e31b131461038d57600080fd5b80639aab92481461027b578063a9e56f3c14610291578063ab8236f3146102c5578063c31c9c07146102e557600080fd5b80635b676ff3116100c65780635b676ff3146101d05780635e1e6325146101e5578063750a1d481461021a5780639881fcb41461024e57600080fd5b80634285f6e4146101035780634588b7c5146101365780634c1ee03e14610182578063544caa56146101a257600080fd5b366100fe57005b600080fd5b34801561010f57600080fd5b5061012361011e366004613a97565b6103bd565b6040519081526020015b60405180910390f35b34801561014257600080fd5b5061016a7f000000000000000000000000d158bd9e8b6efd3ca76830b66715aa2b7bad221881565b6040516001600160a01b03909116815260200161012d565b34801561018e57600080fd5b5061016a61019d366004613af5565b6104ce565b3480156101ae57600080fd5b506101c26101bd366004613b40565b61059e565b60405161012d929190613b79565b6101e36101de366004613bd7565b610696565b005b3480156101f157600080fd5b50610205610200366004613c42565b610e78565b6040805192835290151560208301520161012d565b34801561022657600080fd5b5061016a7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab181565b34801561025a57600080fd5b5061026e610269366004613d4b565b6110cc565b60405161012d9190613d87565b34801561028757600080fd5b5061012360015481565b34801561029d57600080fd5b5061016a7f00000000000000000000000053bf833a5d6c4dda888f69c22c88c9f356a4161481565b3480156102d157600080fd5b506101e36102e0366004613dcb565b61138e565b3480156102f157600080fd5b5061016a7f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156481565b34801561032557600080fd5b5060025461016a906001600160a01b031681565b34801561034557600080fd5b5060005461016a906001600160a01b031681565b34801561036557600080fd5b5061016a7f000000000000000000000000c873fecbd354f5a56e00e710b90ef4201db2448d81565b34801561039957600080fd5b506103ad6103a8366004613e65565b611546565b604051901515815260200161012d565b6000808360e001516040516020016103d59190613e82565b60405160208183030381529060405290507f00000000000000000000000053bf833a5d6c4dda888f69c22c88c9f356a416146001600160a01b0316630a51236985600001516001848760405180606001604052808b610120015181526020018b60c0015181526020018b60e001516040516020016104539190613e82565b6040516020818303038152906040528152506040518663ffffffff1660e01b8152600401610485959493929190613f13565b6040805180830381865afa1580156104a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c59190613f6b565b50949350505050565b60008060006104dd868661059e565b6040516001600160601b0319606084811b8216602084015283901b16603482015286151560f81b604882015291935091507f000000000000000000000000d158bd9e8b6efd3ca76830b66715aa2b7bad221890604901604051602081830303815290604052805190602001207f5a3af0c2a37128debd77e4b5ead274797ab83517588883bccc90813a35706cd360405160200161057c93929190613f8f565b60408051601f1981840301815291905280516020909101209695505050505050565b600080826001600160a01b0316846001600160a01b0316036106115760405162461bcd60e51b815260206004820152602160248201527f426173655631526f757465723a204944454e544943414c5f41444452455353456044820152605360f81b60648201526084015b60405180910390fd5b826001600160a01b0316846001600160a01b031610610631578284610634565b83835b90925090506001600160a01b03821661068f5760405162461bcd60e51b815260206004820152601a60248201527f426173655631526f757465723a205a45524f5f414444524553530000000000006044820152606401610608565b9250929050565b600254600160a01b900460ff166001146106df5760405162461bcd60e51b815260206004820152600a6024820152695245454e5452414e435960b01b6044820152606401610608565b6002805460ff60a01b1916600160a11b179055808314610712576040516373f8993760e11b815260040160405180910390fd5b60005b83811015610e5e57600085858381811061073157610731613fc2565b90506020020160208101906107469190613fe7565b905060001960ff82160161083e5760008085858581811061076957610769613fc2565b905060200281019061077b9190614004565b81019061078891906140b9565b9150915060005b82518110156108365760008282815181106107ac576107ac613fc2565b6020026020010151116107d25760405163fe4155c760e01b815260040160405180910390fd5b61082433308484815181106107e9576107e9613fc2565b602002602001015186858151811061080357610803613fc2565b60200260200101516001600160a01b03166115db909392919063ffffffff16565b8061082e81614189565b91505061078f565b505050610e4b565b60011960ff82160161091a57600084848481811061085e5761085e613fc2565b90506020028101906108709190614004565b81019061087d91906141a2565b9050806000036108a05760405163fe4155c760e01b815260040160405180910390fd5b7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b1580156108fb57600080fd5b505af115801561090f573d6000803e3d6000fd5b505050505050610e4b565b60021960ff8216016109aa57600084848481811061093a5761093a613fc2565b905060200281019061094c9190614004565b81019061095991906141ce565b905060005b81518110156109a357600082828151811061097b5761097b613fc2565b6020026020010151905061098e8161164c565b5050808061099b90614189565b91505061095e565b5050610e4b565b60031960ff821601610a2c5760008484848181106109ca576109ca613fc2565b90506020028101906109dc9190614004565b8101906109e991906142b8565b905060005b81518110156109a357610a19828281518110610a0c57610a0c613fc2565b60200260200101516118cd565b5080610a2481614189565b9150506109ee565b60041960ff821601610aae576000848484818110610a4c57610a4c613fc2565b9050602002810190610a5e9190614004565b810190610a6b91906143ba565b905060005b81518110156109a357610a9b828281518110610a8e57610a8e613fc2565b6020026020010151611b17565b5080610aa681614189565b915050610a70565b60051960ff821601610b30576000848484818110610ace57610ace613fc2565b9050602002810190610ae09190614004565b810190610aed91906144c7565b905060005b81518110156109a357610b1d828281518110610b1057610b10613fc2565b6020026020010151611d0b565b5080610b2881614189565b915050610af2565b60061960ff821601610b9057600080600080878787818110610b5457610b54613fc2565b9050602002810190610b669190614004565b810190610b7391906145c1565b9350935093509350610b8784848484611f48565b50505050610e4b565b600c1960ff821601610d1e57600080858585818110610bb157610bb1613fc2565b9050602002810190610bc39190614004565b810190610bd09190614621565b9150915080600003610c69576040516370a0823160e01b81523060048201527f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b0316906370a0823190602401602060405180830381865afa158015610c40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c64919061464d565b610c6b565b805b604051632e1a7d4d60e01b8152600481018290529091507f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015610cd057600080fd5b505af1158015610ce4573d6000803e3d6000fd5b505050506000610cf3826123b6565b9050610d0883610d038385614666565b6123db565b600254610836906001600160a01b0316826123db565b600d1960ff821601610ddf576000848484818110610d3e57610d3e613fc2565b9050602002810190610d509190614004565b810190610d5d9190614679565b905060005b81518110156109a357610dcd828281518110610d8057610d80613fc2565b602002602001015160000151838381518110610d9e57610d9e613fc2565b602002602001015160400151848481518110610dbc57610dbc613fc2565b602002602001015160200151612431565b80610dd781614189565b915050610d62565b600e1960ff821601610e32576000806000868686818110610e0257610e02613fc2565b9050602002810190610e149190614004565b810190610e2191906147bb565b92509250925061083683838361253a565b6040516379df70e560e11b815260040160405180910390fd5b5080610e5681614189565b915050610715565b50506002805460ff60a01b1916600160a01b179055505050565b6000806000610e89858560016104ce565b60405163e5e31b1360e01b81526001600160a01b03828116600483015291925060009182917f000000000000000000000000d158bd9e8b6efd3ca76830b66715aa2b7bad22189091169063e5e31b1390602401602060405180830381865afa158015610ef9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1d9190614893565b15610f96576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015610f6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f93919061464d565b91505b610fa2878760006104ce565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529194507f000000000000000000000000d158bd9e8b6efd3ca76830b66715aa2b7bad22189091169063e5e31b1390602401602060405180830381865afa15801561100d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110319190614893565b156110aa576040516378a051ad60e11b8152600481018990526001600160a01b03888116602483015284169063f140a35a90604401602060405180830381865afa158015611083573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a7919061464d565b90505b8082116110b9578060006110bd565b8160015b94509450505050935093915050565b60606001825110156111205760405162461bcd60e51b815260206004820152601a60248201527f426173655631526f757465723a20494e56414c49445f504154480000000000006044820152606401610608565b815161112d9060016148b0565b6001600160401b038111156111445761114461383d565b60405190808252806020026020018201604052801561116d578160200160208202803683370190505b509050828160008151811061118457611184613fc2565b60200260200101818152505060005b82518110156113875760006112008483815181106111b3576111b3613fc2565b6020026020010151600001518584815181106111d1576111d1613fc2565b6020026020010151602001518685815181106111ef576111ef613fc2565b6020026020010151604001516104ce565b60405163e5e31b1360e01b81526001600160a01b0380831660048301529192507f000000000000000000000000d158bd9e8b6efd3ca76830b66715aa2b7bad22189091169063e5e31b1390602401602060405180830381865afa15801561126b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128f9190614893565b1561137457806001600160a01b031663f140a35a8484815181106112b5576112b5613fc2565b60200260200101518685815181106112cf576112cf613fc2565b6020026020010151600001516040518363ffffffff1660e01b815260040161130a9291909182526001600160a01b0316602082015260400190565b602060405180830381865afa158015611327573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134b919061464d565b836113578460016148b0565b8151811061136757611367613fc2565b6020026020010181815250505b508061137f81614189565b915050611193565b5092915050565b336001600160a01b037f00000000000000000000000053bf833a5d6c4dda888f69c22c88c9f356a4161416146113d757604051638afe477f60e01b815260040160405180910390fd5b600080620186a081815a6113eb9190614666565b9050600080600087806020019051810190611406919061497e565b925092509250845a1015611438576114286001600160a01b038b16848b612868565b47156114385761143883476123db565b604051635b676ff360e01b81523090635b676ff390869061145f9086908690600401614adf565b600060405180830381600088803b15801561147957600080fd5b5087f19350505050801561148b575060015b6114d9573d8080156114b9576040519150601f19603f3d011682016040523d82523d6000602084013e6114be565b606091505b506114d36001600160a01b038c16858c612868565b60019750505b47156114e9576114e983476123db565b604080518a815288151560208201528715158183015290516001600160a01b038c16917f7f345d6da48bd1339fd428ff45265a0f01258b14ca09dcf8db0c469f4f732fd3919081900360600190a250505050505050505050505050565b60405163e5e31b1360e01b81526001600160a01b0382811660048301526000917f000000000000000000000000d158bd9e8b6efd3ca76830b66715aa2b7bad22189091169063e5e31b1390602401602060405180830381865afa1580156115b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d59190614893565b92915050565b6040516001600160a01b03808516602483015283166044820152606481018290526116469085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612898565b50505050565b80516000901561165d5781516116cb565b60408083015190516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156116a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cb919061464d565b8083526040808401519051636eb1769f60e11b81526001600160a01b039091169063dd62ed3e906117229030907f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156490600401613b79565b602060405180830381865afa15801561173f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611763919061464d565b101561179a5761179a82604001517f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156460001961296a565b6040805161010081018252838201516001600160a01b0390811682526060808601518216602080850191825260808089015162ffffff90811687890190815230958801958652429288019283528a5160a08901908152938b015160c08901908152600060e08a01908152995163414bf38960e01b8152895189166004820152955188166024870152905190911660448501529351851660648401525160848301525160a4820152905160c48201529251811660e484015290917f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615649091169063414bf38990610104015b6020604051808303816000875af11580156118a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c6919061464d565b9392505050565b8051600090156118de57815161194c565b60408083015190516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611928573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194c919061464d565b8083526040808401519051636eb1769f60e11b81526001600160a01b039091169063dd62ed3e906119a39030907f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156490600401613b79565b602060405180830381865afa1580156119c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e4919061464d565b1015611a1b57611a1b82604001517f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156460001961296a565b6040805160a08082018352918401519184015160608086015160c08088015160808901516001600160601b031997851b8816928701929092526001600160e81b031960e895861b811660d488015292841b871660d787015290931b1660eb8401521b90911660ee8201526000908061010281016040516020818303038152906040528152602001306001600160a01b0316815260200142815260200184600001518152602001846020015181525090507f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615646001600160a01b031663c04b8d59826040518263ffffffff1660e01b81526004016118839190614b0d565b805160009015611b28578151611bb3565b8160400151600081518110611b3f57611b3f613fc2565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611b8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bb3919061464d565b8083526000805460408501516001549293611bdc936001600160a01b0390931692909190612a6a565b90508060018251611bed9190614666565b81518110611bfd57611bfd613fc2565b602002602001015191508260200151821015611c5b5760405162461bcd60e51b815260206004820152601760248201527f696e73756666696369656e742d616d6f756e742d6f75740000000000000000006044820152606401610608565b826060015115611cf6576000805460408501518051611cf693611cbe936001600160a01b03169291611c8f57611c8f613fc2565b60200260200101518660400151600181518110611cae57611cae613fc2565b6020026020010151600154612bed565b845160408601518051600090611cd657611cd6613fc2565b60200260200101516001600160a01b03166128689092919063ffffffff16565b611d0581846040015130612c73565b50919050565b6060816060015142811015611d5a5760405162461bcd60e51b815260206004820152601560248201527410985cd9558c549bdd5d195c8e8811561412549151605a1b6044820152606401610608565b825115611d68578251611df4565b8260400151600081518110611d7f57611d7f613fc2565b6020908102919091010151516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611dd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df4919061464d565b8084526040840151611e0691906110cc565b915082602001518260018451611e1c9190614666565b81518110611e2c57611e2c613fc2565b60200260200101511015611e935760405162461bcd60e51b815260206004820152602860248201527f426173655631526f757465723a20494e53554646494349454e545f4f555450556044820152671517d05353d5539560c21b6064820152608401610608565b611f398360400151600081518110611ead57611ead613fc2565b602002602001015160000151611f198560400151600081518110611ed357611ed3613fc2565b6020026020010151600001518660400151600081518110611ef657611ef6613fc2565b60200260200101516020015187604001516000815181106111ef576111ef613fc2565b84600081518110611f2c57611f2c613fc2565b6020026020010151612e4a565b611d0582846040015130612f32565b8315611f545783611fdb565b82600081518110611f6757611f67613fc2565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fdb919061464d565b93508383600081518110611ff157611ff1613fc2565b60200260200101516001600160a01b031663dd62ed3e307f000000000000000000000000c873fecbd354f5a56e00e710b90ef4201db2448d6040518363ffffffff1660e01b8152600401612046929190613b79565b602060405180830381865afa158015612063573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612087919061464d565b10156122f3576000836000815181106120a2576120a2613fc2565b60200260200101516001600160a01b031663dd62ed3e307f000000000000000000000000c873fecbd354f5a56e00e710b90ef4201db2448d6040518363ffffffff1660e01b81526004016120f7929190613b79565b602060405180830381865afa158015612114573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612138919061464d565b111561223e5761223e7f000000000000000000000000c873fecbd354f5a56e00e710b90ef4201db2448d8460008151811061217557612175613fc2565b60200260200101516001600160a01b031663dd62ed3e307f000000000000000000000000c873fecbd354f5a56e00e710b90ef4201db2448d6040518363ffffffff1660e01b81526004016121ca929190613b79565b602060405180830381865afa1580156121e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061220b919061464d565b8560008151811061221e5761221e613fc2565b60200260200101516001600160a01b03166131819092919063ffffffff16565b8260008151811061225157612251613fc2565b602090810291909101015160405163095ea7b360e01b81526001600160a01b037f000000000000000000000000c873fecbd354f5a56e00e710b90ef4201db2448d8116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af11580156122cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f19190614893565b505b60006122ff858561328b565b90507f000000000000000000000000c873fecbd354f5a56e00e710b90ef4201db2448d6001600160a01b031663ac3893ba8683600185516123409190614666565b8151811061235057612350613fc2565b6020026020010151873088886040518763ffffffff1660e01b815260040161237d96959493929190614b9e565b600060405180830381600087803b15801561239757600080fd5b505af11580156123ab573d6000803e3d6000fd5b505050505050505050565b60006127106123c78361270b614be2565b6123d19190614bf9565b6115d59083614666565b600080600080600085875af190508061242c5760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b6044820152606401610608565b505050565b816000036124a6576040516370a0823160e01b81523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa15801561247d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a1919061464d565b6124a8565b815b915060006124b5836123b6565b90506124c18184614666565b6002549093506124de906001600160a01b03868116911683612868565b6124f26001600160a01b0385168385612868565b604080516001600160a01b0386168152602081018390527f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f910160405180910390a150505050565b805182511461255c576040516373f8993760e11b815260040160405180910390fd5b620186a0836101200151101561258557604051636eb14fc360e11b815260040160405180910390fd5b600083610100015183836040516020016125a193929190614c1b565b604051602081830303815290604052905083608001516000036126315760208401516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015612608573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061262c919061464d565b612637565b83608001515b608085018190526020850151604051636eb1769f60e11b81526001600160a01b039091169063dd62ed3e906126929030907f00000000000000000000000053bf833a5d6c4dda888f69c22c88c9f356a4161490600401613b79565b602060405180830381865afa1580156126af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d3919061464d565b101561277557602084015160405163095ea7b360e01b81526001600160a01b037f00000000000000000000000053bf833a5d6c4dda888f69c22c88c9f356a416148116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af115801561274f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127739190614893565b505b7f00000000000000000000000053bf833a5d6c4dda888f69c22c88c9f356a416146001600160a01b0316639fbf10fc47866000015187604001518860600151338a608001518b60a0015160405180606001604052808e610120015181526020018e60c0015181526020018e60e001516040516020016127f49190613e82565b6040516020818303038152906040528152508d60e0015160405160200161281b9190613e82565b6040516020818303038152906040528b6040518b63ffffffff1660e01b815260040161284f99989796959493929190614c5b565b6000604051808303818588803b15801561239757600080fd5b6040516001600160a01b03831660248201526044810182905261242c90849063a9059cbb60e01b9060640161160f565b60006128ed826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166133219092919063ffffffff16565b80519091501561242c578080602001905181019061290b9190614893565b61242c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610608565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291516000928392908716916129c69190614cd8565b6000604051808303816000865af19150503d8060008114612a03576040519150601f19603f3d011682016040523d82523d6000602084013e612a08565b606091505b5091509150818015612a32575080511580612a32575080806020019051810190612a329190614893565b612a635760405162461bcd60e51b8152602060048201526002602482015261534160f01b6044820152606401610608565b5050505050565b6060600283511015612abe5760405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a20494e56414c49445f5041544800006044820152606401610608565b82516001600160401b03811115612ad757612ad761383d565b604051908082528060200260200182016040528015612b00578160200160208202803683370190505b5090508381600081518110612b1757612b17613fc2565b60200260200101818152505060005b60018451612b349190614666565b8110156104c557600080612b8888878581518110612b5457612b54613fc2565b602002602001015188866001612b6a91906148b0565b81518110612b7a57612b7a613fc2565b602002602001015188613338565b91509150612bb0848481518110612ba157612ba1613fc2565b60200260200101518383613404565b84612bbc8560016148b0565b81518110612bcc57612bcc613fc2565b60200260200101818152505050508080612be590614189565b915050612b26565b6000806000612bfc8686613523565b6040516001600160601b0319606084811b8216602084015283901b166034820152919350915087906048016040516020818303038152906040528051906020012085604051602001612c5093929190613f8f565b60408051601f198184030181529190528051602090910120979650505050505050565b60005b60018351612c849190614666565b81101561164657600080848381518110612ca057612ca0613fc2565b602002602001015185846001612cb691906148b0565b81518110612cc657612cc6613fc2565b6020026020010151915091506000612cde8383613523565b509050600087612cef8660016148b0565b81518110612cff57612cff613fc2565b60200260200101519050600080836001600160a01b0316866001600160a01b031614612d2d57826000612d31565b6000835b91509150600060028a51612d459190614666565b8810612d515788612d7e565b600054612d7e906001600160a01b0316878c612d6e8c60026148b0565b81518110611cae57611cae613fc2565b9050612da160008054906101000a90046001600160a01b03168888600154612bed565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f191660200182016040528015612dde576020820181803683370190505b506040518563ffffffff1660e01b8152600401612dfe9493929190614cf4565b600060405180830381600087803b158015612e1857600080fd5b505af1158015612e2c573d6000803e3d6000fd5b50505050505050505050508080612e4290614189565b915050612c76565b6000836001600160a01b03163b11612e6157600080fd5b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151600092839290871691612ebd9190614cd8565b6000604051808303816000865af19150503d8060008114612efa576040519150601f19603f3d011682016040523d82523d6000602084013e612eff565b606091505b5091509150818015612f29575080511580612f29575080806020019051810190612f299190614893565b612a6357600080fd5b60005b8251811015611646576000612f84848381518110612f5557612f55613fc2565b602002602001015160000151858481518110612f7357612f73613fc2565b60200260200101516020015161059e565b509050600085612f958460016148b0565b81518110612fa557612fa5613fc2565b60200260200101519050600080836001600160a01b0316878681518110612fce57612fce613fc2565b6020026020010151600001516001600160a01b031614612ff057826000612ff4565b6000835b915091506000600188516130089190614666565b86106130145786613087565b613087886130238860016148b0565b8151811061303357613033613fc2565b6020026020010151600001518988600161304d91906148b0565b8151811061305d5761305d613fc2565b6020026020010151602001518a89600161307791906148b0565b815181106111ef576111ef613fc2565b90506130da88878151811061309e5761309e613fc2565b6020026020010151600001518988815181106130bc576130bc613fc2565b6020026020010151602001518a89815181106111ef576111ef613fc2565b6001600160a01b031663022c0d9f84848460006040519080825280601f01601f191660200182016040528015613117576020820181803683370190505b506040518563ffffffff1660e01b81526004016131379493929190614cf4565b600060405180830381600087803b15801561315157600080fd5b505af1158015613165573d6000803e3d6000fd5b505050505050505050808061317990614189565b915050612f35565b604051636eb1769f60e11b81526000906001600160a01b0385169063dd62ed3e906131b29030908790600401613b79565b602060405180830381865afa1580156131cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f3919061464d565b9050818110156132575760405162461bcd60e51b815260206004820152602960248201527f5361666545524332303a2064656372656173656420616c6c6f77616e63652062604482015268656c6f77207a65726f60b81b6064820152608401610608565b6040516001600160a01b03841660248201528282036044820181905290612a6390869063095ea7b360e01b9060640161160f565b60405163d06ca61f60e01b81526060906001600160a01b037f000000000000000000000000c873fecbd354f5a56e00e710b90ef4201db2448d169063d06ca61f906132dc9086908690600401614d21565b600060405180830381865afa1580156132f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526118c69190810190614d3a565b60606133308484600085613613565b949350505050565b60008060006133478686613523565b50905060008061335989898989612bed565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015613396573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133ba9190614dd6565b506001600160701b031691506001600160701b03169150826001600160a01b0316886001600160a01b0316146133f15780826133f4565b81815b909a909950975050505050505050565b60008084116134695760405162461bcd60e51b815260206004820152602b60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4960448201526a1394155517d05353d5539560aa1b6064820152608401610608565b6000831180156134795750600082115b6134d65760405162461bcd60e51b815260206004820152602860248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4c604482015267495155494449545960c01b6064820152608401610608565b60006134e4856103e56136e3565b905060006134f282856136e3565b9050600061350c83613506886103e86136e3565b9061374a565b90506135188183614bf9565b979650505050505050565b600080826001600160a01b0316846001600160a01b0316036135955760405162461bcd60e51b815260206004820152602560248201527f556e697377617056324c6962726172793a204944454e544943414c5f41444452604482015264455353455360d81b6064820152608401610608565b826001600160a01b0316846001600160a01b0316106135b55782846135b8565b83835b90925090506001600160a01b03821661068f5760405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a205a45524f5f4144445245535300006044820152606401610608565b6060824710156136745760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610608565b600080866001600160a01b031685876040516136909190614cd8565b60006040518083038185875af1925050503d80600081146136cd576040519150601f19603f3d011682016040523d82523d6000602084013e6136d2565b606091505b50915091506135188783838761379f565b6000811580613707575082826136f98183614be2565b92506137059083614bf9565b145b6115d55760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b6044820152606401610608565b60008261375783826148b0565b91508110156115d55760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b6044820152606401610608565b6060831561380e578251600003613807576001600160a01b0385163b6138075760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610608565b5081613330565b61333083838151156138235781518083602001fd5b8060405162461bcd60e51b81526004016106089190614e1b565b634e487b7160e01b600052604160045260246000fd5b60405161016081016001600160401b03811182821017156138765761387661383d565b60405290565b604051606081016001600160401b03811182821017156138765761387661383d565b60405160a081016001600160401b03811182821017156138765761387661383d565b60405160e081016001600160401b03811182821017156138765761387661383d565b604051608081016001600160401b03811182821017156138765761387661383d565b604051601f8201601f191681016001600160401b038111828210171561392c5761392c61383d565b604052919050565b803561ffff8116811461394657600080fd5b919050565b6001600160a01b038116811461396057600080fd5b50565b80356139468161394b565b6000610160828403121561398157600080fd5b613989613853565b905061399482613934565b81526139a260208301613963565b602082015260408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013560c08201526139e560e08301613963565b60e08201526101006139f8818401613963565b9082015261012082810135908201526101409182013591810191909152919050565b60006001600160401b03821115613a3357613a3361383d565b50601f01601f191660200190565b600082601f830112613a5257600080fd5b8135613a65613a6082613a1a565b613904565b818152846020838601011115613a7a57600080fd5b816020850160208301376000918101602001919091529392505050565b6000806101808385031215613aab57600080fd5b613ab5848461396e565b91506101608301356001600160401b03811115613ad157600080fd5b613add85828601613a41565b9150509250929050565b801515811461396057600080fd5b600080600060608486031215613b0a57600080fd5b8335613b158161394b565b92506020840135613b258161394b565b91506040840135613b3581613ae7565b809150509250925092565b60008060408385031215613b5357600080fd5b8235613b5e8161394b565b91506020830135613b6e8161394b565b809150509250929050565b6001600160a01b0392831681529116602082015260400190565b60008083601f840112613ba557600080fd5b5081356001600160401b03811115613bbc57600080fd5b6020830191508360208260051b850101111561068f57600080fd5b60008060008060408587031215613bed57600080fd5b84356001600160401b0380821115613c0457600080fd5b613c1088838901613b93565b90965094506020870135915080821115613c2957600080fd5b50613c3687828801613b93565b95989497509550505050565b600080600060608486031215613c5757600080fd5b833592506020840135613c698161394b565b91506040840135613b358161394b565b60006001600160401b03821115613c9257613c9261383d565b5060051b60200190565b600082601f830112613cad57600080fd5b81356020613cbd613a6083613c79565b82815260609283028501820192828201919087851115613cdc57600080fd5b8387015b85811015613d3e5781818a031215613cf85760008081fd5b613d0061387c565b8135613d0b8161394b565b815281860135613d1a8161394b565b81870152604082810135613d2d81613ae7565b908201528452928401928101613ce0565b5090979650505050505050565b60008060408385031215613d5e57600080fd5b8235915060208301356001600160401b03811115613d7b57600080fd5b613add85828601613c9c565b6020808252825182820181905260009190848201906040850190845b81811015613dbf57835183529284019291840191600101613da3565b50909695505050505050565b60008060008060008060c08789031215613de457600080fd5b613ded87613934565b955060208701356001600160401b0380821115613e0957600080fd5b613e158a838b01613a41565b96506040890135955060608901359150613e2e8261394b565b9093506080880135925060a08801359080821115613e4b57600080fd5b50613e5889828a01613a41565b9150509295509295509295565b600060208284031215613e7757600080fd5b81356118c68161394b565b60609190911b6001600160601b031916815260140190565b60005b83811015613eb5578181015183820152602001613e9d565b50506000910152565b60008151808452613ed6816020860160208601613e9a565b601f01601f19169290920160200192915050565b805182526020810151602083015260006040820151606060408501526133306060850182613ebe565b61ffff8616815260ff8516602082015260a060408201526000613f3960a0830186613ebe565b8281036060840152613f4b8186613ebe565b90508281036080840152613f5f8185613eea565b98975050505050505050565b60008060408385031215613f7e57600080fd5b505080516020909101519092909150565b6001600160f81b0319815260609390931b6001600160601b03191660018401526015830191909152603582015260550190565b634e487b7160e01b600052603260045260246000fd5b60ff8116811461396057600080fd5b600060208284031215613ff957600080fd5b81356118c681613fd8565b6000808335601e1984360301811261401b57600080fd5b8301803591506001600160401b0382111561403557600080fd5b60200191503681900382131561068f57600080fd5b600082601f83011261405b57600080fd5b8135602061406b613a6083613c79565b82815260059290921b8401810191818101908684111561408a57600080fd5b8286015b848110156140ae5780356140a18161394b565b835291830191830161408e565b509695505050505050565b600080604083850312156140cc57600080fd5b82356001600160401b03808211156140e357600080fd5b6140ef8683870161404a565b935060209150818501358181111561410657600080fd5b85019050601f8101861361411957600080fd5b8035614127613a6082613c79565b81815260059190911b8201830190838101908883111561414657600080fd5b928401925b828410156141645783358252928401929084019061414b565b80955050505050509250929050565b634e487b7160e01b600052601160045260246000fd5b60006001820161419b5761419b614173565b5060010190565b6000602082840312156141b457600080fd5b5035919050565b803562ffffff8116811461394657600080fd5b600060208083850312156141e157600080fd5b82356001600160401b038111156141f757600080fd5b8301601f8101851361420857600080fd5b8035614216613a6082613c79565b81815260a0918202830184019184820191908884111561423557600080fd5b938501935b838510156142ac5780858a0312156142525760008081fd5b61425a61389e565b8535815286860135878201526040808701356142758161394b565b908201526060868101356142888161394b565b9082015260806142998782016141bb565b908201528352938401939185019161423a565b50979650505050505050565b600060208083850312156142cb57600080fd5b82356001600160401b038111156142e157600080fd5b8301601f810185136142f257600080fd5b8035614300613a6082613c79565b81815260e0918202830184019184820191908884111561431f57600080fd5b938501935b838510156142ac5780858a03121561433c5760008081fd5b6143446138c0565b85358152868601358782015260408087013561435f8161394b565b908201526060868101356143728161394b565b908201526080868101356143858161394b565b9082015260a06143968782016141bb565b9082015260c06143a78782016141bb565b9082015283529384019391850191614324565b600060208083850312156143cd57600080fd5b82356001600160401b03808211156143e457600080fd5b818501915085601f8301126143f857600080fd5b8135614406613a6082613c79565b81815260059190911b8301840190848101908883111561442557600080fd5b8585015b838110156144ba5780358581111561444057600080fd5b86016080818c03601f190112156144575760008081fd5b61445f6138e2565b8882013581526040808301358a830152606080840135898111156144835760008081fd5b6144918f8d8388010161404a565b8385015250608084013593506144a684613ae7565b820192909252845250918601918601614429565b5098975050505050505050565b600060208083850312156144da57600080fd5b82356001600160401b03808211156144f157600080fd5b818501915085601f83011261450557600080fd5b8135614513613a6082613c79565b81815260059190911b8301840190848101908883111561453257600080fd5b8585015b838110156144ba5780358581111561454d57600080fd5b86016080818c03601f190112156145645760008081fd5b61456c6138e2565b8882013581526040808301358a830152606080840135898111156145905760008081fd5b61459e8f8d83880101613c9c565b928401929092526080939093013592820192909252845250918601918601614536565b600080600080608085870312156145d757600080fd5b8435935060208501356001600160401b038111156145f457600080fd5b6146008782880161404a565b93505060408501356146118161394b565b9396929550929360600135925050565b6000806040838503121561463457600080fd5b823561463f8161394b565b946020939093013593505050565b60006020828403121561465f57600080fd5b5051919050565b818103818111156115d5576115d5614173565b6000602080838503121561468c57600080fd5b82356001600160401b038111156146a257600080fd5b8301601f810185136146b357600080fd5b80356146c1613a6082613c79565b818152606091820283018401918482019190888411156146e057600080fd5b938501935b838510156142ac5780858a0312156146fd5760008081fd5b61470561387c565b85356147108161394b565b81528587013561471f8161394b565b8188015260408681013590820152835293840193918501916146e5565b600082601f83011261474d57600080fd5b8135602061475d613a6083613c79565b82815260059290921b8401810191818101908684111561477c57600080fd5b8286015b848110156140ae5780356001600160401b0381111561479f5760008081fd5b6147ad8986838b0101613a41565b845250918301918301614780565b60008060006101a084860312156147d157600080fd5b6147db858561396e565b92506101608401356001600160401b03808211156147f857600080fd5b818601915086601f83011261480c57600080fd5b8135602061481c613a6083613c79565b82815260059290921b8401810191818101908a84111561483b57600080fd5b948201945b8386101561486257853561485381613fd8565b82529482019490820190614840565b965050505061018086013591508082111561487c57600080fd5b506148898682870161473c565b9150509250925092565b6000602082840312156148a557600080fd5b81516118c681613ae7565b808201808211156115d5576115d5614173565b600082601f8301126148d457600080fd5b815160206148e4613a6083613c79565b82815260059290921b8401810191818101908684111561490357600080fd5b8286015b848110156140ae5780516001600160401b038111156149265760008081fd5b8701603f810189136149385760008081fd5b84810151604061494a613a6083613a1a565b8281528b8284860101111561495f5760008081fd5b61496e83898301848701613e9a565b8652505050918301918301614907565b60008060006060848603121561499357600080fd5b835161499e8161394b565b809350506020808501516001600160401b03808211156149bd57600080fd5b818701915087601f8301126149d157600080fd5b81516149df613a6082613c79565b81815260059190911b8301840190848101908a8311156149fe57600080fd5b938501935b82851015614a25578451614a1681613fd8565b82529385019390850190614a03565b60408a01519097509450505080831115614a3e57600080fd5b5050614889868287016148c3565b600081518084526020808501945080840160005b83811015614a7f57815160ff1687529582019590820190600101614a60565b509495945050505050565b600081518084526020808501808196508360051b8101915082860160005b85811015614ad2578284038952614ac0848351613ebe565b98850198935090840190600101614aa8565b5091979650505050505050565b604081526000614af26040830185614a4c565b8281036020840152614b048185614a8a565b95945050505050565b602081526000825160a06020840152614b2960c0840182613ebe565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b600081518084526020808501945080840160005b83811015614a7f5781516001600160a01b031687529582019590820190600101614b79565b86815285602082015260c060408201526000614bbd60c0830187614b65565b6001600160a01b03958616606084015293909416608082015260a00152949350505050565b80820281158282048414176115d5576115d5614173565b600082614c1657634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b0384168152606060208201819052600090614c3f90830185614a4c565b8281036040840152614c518185614a8a565b9695505050505050565b600061012061ffff8c1683528a602084015289604084015260018060a01b03891660608401528760808401528660a08401528060c0840152614c9f81840187613eea565b905082810360e0840152614cb38186613ebe565b9050828103610100840152614cc88185613ebe565b9c9b505050505050505050505050565b60008251614cea818460208701613e9a565b9190910192915050565b84815283602082015260018060a01b0383166040820152608060608201526000614c516080830184613ebe565b8281526040602082015260006133306040830184614b65565b60006020808385031215614d4d57600080fd5b82516001600160401b03811115614d6357600080fd5b8301601f81018513614d7457600080fd5b8051614d82613a6082613c79565b81815260059190911b82018301908381019087831115614da157600080fd5b928401925b8284101561351857835182529284019290840190614da6565b80516001600160701b038116811461394657600080fd5b600080600060608486031215614deb57600080fd5b614df484614dbf565b9250614e0260208501614dbf565b9150604084015163ffffffff81168114613b3557600080fd5b6020815260006118c66020830184613ebe56fea2646970667358221220545f4b54ff83e127a1f3592a25603d126e070df8f5d0aadced82f2cd4eb8381b64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564000000000000000000000000b09f29e2ba229fdb2bb68dd0e2049a76c014ac8a000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4e18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303000000000000000000000000d158bd9e8b6efd3ca76830b66715aa2b7bad2218000000000000000000000000c873fecbd354f5a56e00e710b90ef4201db2448d00000000000000000000000053bf833a5d6c4dda888f69c22c88c9f356a41614
-----Decoded View---------------
Arg [0] : _weth (address): 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1
Arg [1] : _swapRouter (address): 0xE592427A0AEce92De3Edee1F18E0157C05861564
Arg [2] : _feeCollector (address): 0xB09f29E2BA229FdB2bB68dD0e2049a76C014aC8A
Arg [3] : _factory (address): 0xc35DADB65012eC5796536bD9864eD8773aBc74C4
Arg [4] : _pairCodeHash (bytes32): 0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303
Arg [5] : _xcalFactory (address): 0xD158bd9E8b6efd3ca76830B66715Aa2b7Bad2218
Arg [6] : _camelotRouter (address): 0xc873fEcbd354f5A56E00E710B90EF4201db2448d
Arg [7] : _stargateRouter (address): 0x53Bf833A5d6c4ddA888F69c22C88C9f356a41614
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
Arg [1] : 000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
Arg [2] : 000000000000000000000000b09f29e2ba229fdb2bb68dd0e2049a76c014ac8a
Arg [3] : 000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4
Arg [4] : e18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303
Arg [5] : 000000000000000000000000d158bd9e8b6efd3ca76830b66715aa2b7bad2218
Arg [6] : 000000000000000000000000c873fecbd354f5a56e00e710b90ef4201db2448d
Arg [7] : 00000000000000000000000053bf833a5d6c4dda888f69c22c88c9f356a41614
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$59.43
Net Worth in ETH
0.024357
Token Allocations
USDT
68.69%
USDC
31.31%
MNT
0.00%
Multichain Portfolio | 35 Chains
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.