AVAX Price: $50.43 (-2.41%)
 

Overview

AVAX Balance

Avalanche C-Chain LogoAvalanche C-Chain LogoAvalanche C-Chain Logo0 AVAX

AVAX Value

$0.00

Token Holdings

Transaction Hash
Method
Block
From
To
Cook354399452023-09-20 19:01:54451 days ago1695236514IN
SushiXSwap
1.45597723 AVAX0.0143529725
Cook354392012023-09-20 18:36:56451 days ago1695235016IN
SushiXSwap
0.13504217 AVAX0.0157062626.54256245
Cook354389372023-09-20 18:27:47451 days ago1695234467IN
SushiXSwap
0.13504217 AVAX0.0156820326.5
Cook354382842023-09-20 18:05:50451 days ago1695233150IN
SushiXSwap
0.14397973 AVAX0.016553326.5
Cook354375202023-09-20 17:40:15451 days ago1695231615IN
SushiXSwap
0.62426263 AVAX0.0156912525
Cook354370322023-09-20 17:23:57451 days ago1695230637IN
SushiXSwap
0.41366825 AVAX0.0152335526.5
Cook354369532023-09-20 17:21:18451 days ago1695230478IN
SushiXSwap
0.32395978 AVAX0.0166075526.5
Cook354366012023-09-20 17:09:33451 days ago1695229773IN
SushiXSwap
0.54887127 AVAX0.016509526.5
Cook354346612023-09-20 16:04:14451 days ago1695225854IN
SushiXSwap
0.33018074 AVAX0.0163354326
Cook354339692023-09-20 15:40:55451 days ago1695224455IN
SushiXSwap
0.04218378 AVAX0.0141678826.5
Cook354331332023-09-20 15:12:54451 days ago1695222774IN
SushiXSwap
2.18292628 AVAX0.0192160226.5
Cook354330212023-09-20 15:09:07451 days ago1695222547IN
SushiXSwap
0.09067646 AVAX0.0196240526.3254
Cook354328792023-09-20 15:04:22451 days ago1695222262IN
SushiXSwap
1.31110643 AVAX0.015134626.5
Cook354325632023-09-20 14:53:45451 days ago1695221625IN
SushiXSwap
0.04231568 AVAX0.0156706926.5
Cook354323442023-09-20 14:46:04451 days ago1695221164IN
SushiXSwap
0.30325597 AVAX0.017728226
Cook354322922023-09-20 14:44:04451 days ago1695221044IN
SushiXSwap
1.82067774 AVAX0.0193233226.5
Cook354322302023-09-20 14:41:44451 days ago1695220904IN
SushiXSwap
1.54541179 AVAX0.0185299926.5
Cook354321672023-09-20 14:39:27451 days ago1695220767IN
SushiXSwap
3.34273861 AVAX0.0166385526.5
Cook354321262023-09-20 14:38:05451 days ago1695220685IN
SushiXSwap
0.08807125 AVAX0.0157253626.5
Cook354318652023-09-20 14:29:20451 days ago1695220160IN
SushiXSwap
0.9924229 AVAX0.0152705726.5
Cook354317652023-09-20 14:26:00451 days ago1695219960IN
SushiXSwap
0.59490865 AVAX0.0166938626.5
Cook354316942023-09-20 14:23:37451 days ago1695219817IN
SushiXSwap
0.51242542 AVAX0.0167990526.765
Cook354313292023-09-20 14:11:20451 days ago1695219080IN
SushiXSwap
0.13547891 AVAX0.0198951126.5
Cook354312042023-09-20 14:07:00451 days ago1695218820IN
SushiXSwap
0.4838983 AVAX0.0167167426.765
Cook354308392023-09-20 13:54:44451 days ago1695218084IN
SushiXSwap
0.65563933 AVAX0.0167729826.765
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
354423022023-09-20 20:21:05451 days ago1695241265
SushiXSwap
0.33537869 AVAX
354423022023-09-20 20:21:05451 days ago1695241265
SushiXSwap
0.33537869 AVAX
354406652023-09-20 19:25:49451 days ago1695237949
SushiXSwap
0.3361239 AVAX
354406652023-09-20 19:25:49451 days ago1695237949
SushiXSwap
0.3361239 AVAX
354402732023-09-20 19:12:56451 days ago1695237176
SushiXSwap
1.78826343 AVAX
354402732023-09-20 19:12:56451 days ago1695237176
SushiXSwap
1.78826343 AVAX
354400602023-09-20 19:05:47451 days ago1695236747
SushiXSwap
0.47400748 AVAX
354400602023-09-20 19:05:47451 days ago1695236747
SushiXSwap
0.47400748 AVAX
354400262023-09-20 19:04:39451 days ago1695236679
SushiXSwap
0.19986624 AVAX
354400262023-09-20 19:04:39451 days ago1695236679
SushiXSwap
0.19986624 AVAX
354399452023-09-20 19:01:54451 days ago1695236514
SushiXSwap
0.22560719 AVAX
354399452023-09-20 19:01:54451 days ago1695236514
SushiXSwap
1.23037003 AVAX
354396732023-09-20 18:52:44451 days ago1695235964
SushiXSwap
0.21598214 AVAX
354396732023-09-20 18:52:44451 days ago1695235964
SushiXSwap
0.21598214 AVAX
354395662023-09-20 18:49:11451 days ago1695235751
SushiXSwap
0.14038788 AVAX
354395662023-09-20 18:49:11451 days ago1695235751
SushiXSwap
0.14038788 AVAX
354392892023-09-20 18:39:55451 days ago1695235195
SushiXSwap
0.54966258 AVAX
354392892023-09-20 18:39:55451 days ago1695235195
SushiXSwap
0.54966258 AVAX
354392012023-09-20 18:36:56451 days ago1695235016
SushiXSwap
0.13504217 AVAX
354390142023-09-20 18:30:32451 days ago1695234632
SushiXSwap
0.17934194 AVAX
354390142023-09-20 18:30:32451 days ago1695234632
SushiXSwap
0.17934194 AVAX
354390002023-09-20 18:30:04451 days ago1695234604
SushiXSwap
0.16887996 AVAX
354390002023-09-20 18:30:04451 days ago1695234604
SushiXSwap
0.16887996 AVAX
354389742023-09-20 18:29:10451 days ago1695234550
SushiXSwap
0.01185877 AVAX
354389742023-09-20 18:29:10451 days ago1695234550
SushiXSwap
0.01185877 AVAX
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SushiXSwap

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
Yes with 999999 runs

Other Settings:
default evmVersion
File 1 of 25 : SushiXSwap.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

import "./interfaces/ISushiXSwap.sol";

/// @title SushiXSwap
/// @notice Enables cross chain swap for sushiswap.
/// @dev Supports both BentoBox and Wallet. Supports both Trident and Legacy AMM. Uses Stargate as bridge.
contract SushiXSwap is
    ISushiXSwap,
    BentoAdapter,
    TokenAdapter,
    SushiLegacyAdapter,
    TridentSwapAdapter,
    StargateAdapter
{
    constructor(
        IBentoBoxMinimal _bentoBox,
        IStargateRouter _stargateRouter,
        address _factory,
        bytes32 _pairCodeHash,
        IStargateWidget _stargateWidget
    ) ImmutableState(_bentoBox, _stargateRouter, _factory, _pairCodeHash, _stargateWidget) {
        // Register to BentoBox
        _bentoBox.registerProtocol();
    }

    /// @notice List of ACTIONS supported by the `cook()`.

    // Bento and Token Operations
    uint8 internal constant ACTION_MASTER_CONTRACT_APPROVAL = 0;
    uint8 internal constant ACTION_SRC_DEPOSIT_TO_BENTOBOX = 1;
    uint8 internal constant ACTION_SRC_TRANSFER_FROM_BENTOBOX = 2;
    uint8 internal constant ACTION_DST_DEPOSIT_TO_BENTOBOX = 3;
    uint8 internal constant ACTION_DST_WITHDRAW_TOKEN = 4;
    uint8 internal constant ACTION_DST_WITHDRAW_OR_TRANSFER_FROM_BENTOBOX = 5;
    uint8 internal constant ACTION_UNWRAP_AND_TRANSFER = 6;

    // Swap Operations
    uint8 internal constant ACTION_LEGACY_SWAP = 7;
    uint8 internal constant ACTION_TRIDENT_SWAP = 8;
    uint8 internal constant ACTION_TRIDENT_COMPLEX_PATH_SWAP = 9;

    // Bridge Operations
    uint8 internal constant ACTION_STARGATE_TELEPORT = 10;

    uint8 internal constant ACTION_SRC_TOKEN_TRANSFER = 11;

    /// @notice Executes a set of actions and allows composability (contract calls) to other contracts.
    /// @param actions An array with a sequence of actions to execute (see ACTION_ declarations).
    /// @param values A one-to-one mapped array to `actions`. Native token amount to send along action.
    /// @param datas A one-to-one mapped array to `actions`. Contains abi encoded data of function arguments.
    /// @dev The function gets invoked both at the src and dst chain.
    function cook(
        uint8[] memory actions,
        uint256[] memory values,
        bytes[] memory datas
    ) public payable override {
        uint256 actionLength = actions.length;
        for (uint256 i; i < actionLength; i = _increment(i)) {
            uint8 action = actions[i];
            // update for total amounts in contract?
            if (action == ACTION_MASTER_CONTRACT_APPROVAL) {
                (
                    address user,
                    bool approved,
                    uint8 v,
                    bytes32 r,
                    bytes32 s
                ) = abi.decode(
                        datas[i],
                        (address, bool, uint8, bytes32, bytes32)
                    );

                bentoBox.setMasterContractApproval(
                    user,
                    address(this),
                    approved,
                    v,
                    r,
                    s
                );
            } else if (action == ACTION_SRC_DEPOSIT_TO_BENTOBOX) {
                (address token, address to, uint256 amount, uint256 share) = abi
                    .decode(datas[i], (address, address, uint256, uint256));
                _depositToBentoBox(
                    token,
                    msg.sender,
                    to,
                    amount,
                    share,
                    values[i]
                );
            } else if (action == ACTION_SRC_TRANSFER_FROM_BENTOBOX) {
                (
                    address token,
                    address to,
                    uint256 amount,
                    uint256 share,
                    bool unwrapBento
                ) = abi.decode(
                        datas[i],
                        (address, address, uint256, uint256, bool)
                    );
                _transferFromBentoBox(
                    token,
                    msg.sender,
                    to,
                    amount,
                    share,
                    unwrapBento
                );
            } else if (action == ACTION_SRC_TOKEN_TRANSFER) {
                (address token, address to, uint256 amount) = abi.decode(
                    datas[i],
                    (address, address, uint256)
                );

                _transferFromToken(IERC20(token), to, amount);
            } else if (action == ACTION_DST_DEPOSIT_TO_BENTOBOX) {
                (address token, address to, uint256 amount, uint256 share) = abi
                    .decode(datas[i], (address, address, uint256, uint256));

                if (amount == 0) {
                    amount = IERC20(token).balanceOf(address(this));
                    // Stargate Router doesn't support value? Should we update it anyway?
                    // values[i] = address(this).balance;
                }

                _transferTokens(IERC20(token), address(bentoBox), amount);

                _depositToBentoBox(
                    token,
                    address(bentoBox),
                    to,
                    amount,
                    share,
                    values[i]
                );
            } else if (action == ACTION_DST_WITHDRAW_TOKEN) {
                (address token, address to, uint256 amount) = abi.decode(
                    datas[i],
                    (address, address, uint256)
                );
                if (amount == 0) {
                    if (token != address(0)) {
                        amount = IERC20(token).balanceOf(address(this));
                    } else {
                        amount = address(this).balance;
                    }
                }
                _transferTokens(IERC20(token), to, amount);
            } else if (
                action == ACTION_DST_WITHDRAW_OR_TRANSFER_FROM_BENTOBOX
            ) {
                (
                    address token,
                    address to,
                    uint256 amount,
                    uint256 share,
                    bool unwrapBento
                ) = abi.decode(
                        datas[i],
                        (address, address, uint256, uint256, bool)
                    );
                if (amount == 0 && share == 0) {
                    share = bentoBox.balanceOf(token, address(this));
                }
                _transferFromBentoBox(
                    token,
                    address(this),
                    to,
                    amount,
                    share,
                    unwrapBento
                );
            } else if (action == ACTION_UNWRAP_AND_TRANSFER) {
                (address token, address to) = abi.decode(
                    datas[i],
                    (address, address)
                );

                _unwrapTransfer(token, to);
            } else if (action == ACTION_LEGACY_SWAP) {
                (
                    uint256 amountIn,
                    uint256 amountOutMin,
                    address[] memory path,
                    address to
                ) = abi.decode(
                        datas[i],
                        (uint256, uint256, address[], address)
                    );
                bool sendTokens;
                if (amountIn == 0) {
                    amountIn = IERC20(path[0]).balanceOf(address(this));
                    sendTokens = true;
                }
                _swapExactTokensForTokens(
                    amountIn,
                    amountOutMin,
                    path,
                    to,
                    sendTokens
                );
            } else if (action == ACTION_TRIDENT_SWAP) {
                ExactInputParams memory params = abi.decode(
                    datas[i],
                    (ExactInputParams)
                );

                _exactInput(params);
            } else if (action == ACTION_TRIDENT_COMPLEX_PATH_SWAP) {
                ComplexPathParams memory params = abi.decode(
                    datas[i],
                    (ComplexPathParams)
                );

                _complexPath(params);
            } else if (action == ACTION_STARGATE_TELEPORT) {
                (
                    StargateTeleportParams memory params,
                    uint8[] memory actionsDST,
                    uint256[] memory valuesDST,
                    bytes[] memory datasDST
                ) = abi.decode(
                        datas[i],
                        (StargateTeleportParams, uint8[], uint256[], bytes[])
                    );

                _stargateTeleport(params, actionsDST, valuesDST, datasDST);
            }
        }
    }

    /// @notice Allows the contract to receive Native tokens
    receive() external payable {}
}

File 2 of 25 : ISushiXSwap.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

import "../adapters/BentoAdapter.sol";
import "../adapters/TokenAdapter.sol";
import "../adapters/SushiLegacyAdapter.sol";
import "../adapters/TridentSwapAdapter.sol";
import "../adapters/StargateAdapter.sol";

interface ISushiXSwap {
    function cook(
        uint8[] memory actions,
        uint256[] memory values,
        bytes[] memory datas
    ) external payable;
}

File 3 of 25 : BentoAdapter.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

import "../interfaces/IBentoBoxMinimal.sol";
import "../base/ImmutableState.sol";

/// @title BentoAdapter
/// @notice Adapter which provides all functions of BentoBox require by this contract.
/// @dev These are generic functions, make sure, only msg.sender, address(this) and address(bentoBox)
/// are passed in the from param, or else the attacker can sifu user's funds in bentobox.
abstract contract BentoAdapter is ImmutableState {
    /// @notice Deposits the token from users wallet into the BentoBox.
    /// @dev Make sure, only msg.sender, address(this) and address(bentoBox)
    /// are passed in the from param, or else the attacker can sifu user's funds in bentobox.
    /// Pass either amount or share.
    /// @param token token to deposit. Use token as address(0) when depositing native token
    /// @param from sender
    /// @param to receiver
    /// @param amount amount to be deposited
    /// @param share share to be deposited
    /// @param value native token value to be deposited. Only use when token address is address(0)
    function _depositToBentoBox(
        address token,
        address from,
        address to,
        uint256 amount,
        uint256 share,
        uint256 value
    ) internal {
        bentoBox.deposit{value: value}(token, from, to, amount, share);
    }

    /// @notice Transfers the token from bentobox user to another or withdraw it to another address.
    /// @dev Make sure, only msg.sender, address(this) and address(bentoBox)
    /// are passed in the from param, or else the attacker can sifu user's funds in bentobox.
    /// Pass either amount or share.
    /// @param token token to transfer. For native tokens, use wnative token address
    /// @param from sender
    /// @param to receiver
    /// @param amount amount to transfer
    /// @param share share to transfer
    /// @param unwrapBento use true for withdraw and false for transfer
    function _transferFromBentoBox(
        address token,
        address from,
        address to,
        uint256 amount,
        uint256 share,
        bool unwrapBento
    ) internal {
        if (unwrapBento) {
            bentoBox.withdraw(token, from, to, amount, share);
        } else {
            if (amount > 0) {
                share = bentoBox.toShare(token, amount, false);
            }
            bentoBox.transfer(token, from, to, share);
        }
    }
}

File 4 of 25 : TokenAdapter.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IWETH.sol";

/// @title TokenAdapter
/// @notice Adapter for all token operations
abstract contract TokenAdapter {
    using SafeERC20 for IERC20;

    /// @notice Function to transfer tokens from address(this)
    /// @param token token to transfer
    /// @param to receiver
    /// @param amount amount to transfer
    function _transferTokens(
        IERC20 token,
        address to,
        uint256 amount
    ) internal {
        if (address(token) != address(0)) {
            token.safeTransfer(to, amount);
        } else {
            payable(to).transfer(amount);
        }
    }

    /// @notice Function to transfer tokens from user to the to address
    /// @param token token to transfer
    /// @param to receiver
    /// @param amount amount to transfer
    function _transferFromToken(
        IERC20 token,
        address to,
        uint256 amount
    ) internal {
        token.safeTransferFrom(msg.sender, to, amount);
    }

    /// @notice Unwraps the wrapper native into native and sends it to the receiver.
    /// @param token token to transfer
    /// @param to receiver
    function _unwrapTransfer(address token, address to) internal {
        IWETH(token).withdraw(IERC20(token).balanceOf(address(this)));
        _transferTokens(IERC20(address(0)), to, address(this).balance);
    }
}

File 5 of 25 : SushiLegacyAdapter.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../libraries/UniswapV2Library.sol";
import "../base/ImmutableState.sol";

/// @title SushiLegacyAdapter
/// @notice Adapter for functions used to swap using Sushiswap Legacy AMM.
abstract contract SushiLegacyAdapter is ImmutableState {
    using SafeERC20 for IERC20;

    function _swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] memory path,
        address to,
        bool sendTokens
    ) internal returns (uint256 amountOut) {
        uint256[] memory amounts = UniswapV2Library.getAmountsOut(
            factory,
            amountIn,
            path,
            pairCodeHash
        );
        amountOut = amounts[amounts.length - 1];

        require(amountOut >= amountOutMin, "insufficient-amount-out");

        /// @dev force sends token to the first pair if not already sent
        if (sendTokens) {
            IERC20(path[0]).safeTransfer(
                UniswapV2Library.pairFor(
                    factory,
                    path[0],
                    path[1],
                    pairCodeHash
                ),
                IERC20(path[0]).balanceOf(address(this))
            );
        }
        _swap(amounts, path, to);
    }

    /// @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));
        }
    }
}

File 6 of 25 : TridentSwapAdapter.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

import "../interfaces/trident/ITridentSwapAdapter.sol";

/// @title TridentSwapAdapter
/// @notice Adapter for all Trident based Swaps

abstract contract TridentSwapAdapter is
    ITridentRouter,
    ImmutableState,
    BentoAdapter,
    TokenAdapter
{
    // Custom Error
    error TooLittleReceived();

    /// @notice Swaps token A to token B directly. Swaps are done on `bento` tokens.
    /// @param params This includes the address of token A, pool, amount of token A to swap,
    /// minimum amount of token B after the swap and data required by the pool for the swap.
    /// @dev Ensure that the pool is trusted before calling this function. The pool can steal users' tokens.
    function _exactInput(ExactInputParams memory params)
        internal
        returns (uint256 amountOut)
    {
        if (params.amountIn == 0) {
          uint256 tokenBalance = IERC20(params.tokenIn).balanceOf(
                address(this)
            );
            _transferTokens(
                IERC20(params.tokenIn),
                address(bentoBox),
                tokenBalance
            );
            // Pay the first pool directly.
            (, params.amountIn) = bentoBox.deposit(
                params.tokenIn,
                address(bentoBox),
                params.path[0].pool,
                tokenBalance,
                0
            );
        }

        // Call every pool in the path.
        // Pool `N` should transfer its output tokens to pool `N+1` directly.
        // The last pool should transfer its output tokens to the user.
        // If the user wants to unwrap `wETH`, the final destination should be this contract and
        // a batch call should be made to `unwrapWETH`.
        uint256 n = params.path.length;
        for (uint256 i = 0; i < n; i = _increment(i)) {
            amountOut = IPool(params.path[i].pool).swap(params.path[i].data);
        }
        // Ensure that the slippage wasn't too much. This assumes that the pool is honest.
        if (amountOut < params.amountOutMinimum) revert TooLittleReceived();
    }

    /// @notice Swaps multiple input tokens to multiple output tokens using multiple paths, in different percentages.
    /// For example, you can swap 50 DAI + 100 USDC into 60% ETH and 40% BTC.
    /// @param params This includes everything needed for the swap.
    /// Look at the `ComplexPathParams` struct for more details.
    /// @dev This function is not optimized for single swaps and should only be used in complex cases where
    /// the amounts are large enough that minimizing slippage by using multiple paths is worth the extra gas.
    function _complexPath(ComplexPathParams memory params) internal {
        // Deposit all initial tokens to respective pools and initiate the swaps.
        // Input tokens come from the user - output goes to following pools.
        uint256 n = params.initialPath.length;
        for (uint256 i = 0; i < n; i = _increment(i)) {
            bentoBox.transfer(
                params.initialPath[i].tokenIn,
                address(this),
                params.initialPath[i].pool,
                params.initialPath[i].amount
            );
            IPool(params.initialPath[i].pool).swap(params.initialPath[i].data);
        }
        // Do all the middle swaps. Input comes from previous pools.
        n = params.percentagePath.length;
        for (uint256 i = 0; i < n; i = _increment(i)) {
            uint256 balanceShares = bentoBox.balanceOf(
                params.percentagePath[i].tokenIn,
                address(this)
            );
            uint256 transferShares = (balanceShares *
                params.percentagePath[i].balancePercentage) / uint256(10)**8;
            bentoBox.transfer(
                params.percentagePath[i].tokenIn,
                address(this),
                params.percentagePath[i].pool,
                transferShares
            );
            IPool(params.percentagePath[i].pool).swap(
                params.percentagePath[i].data
            );
        }
        // Ensure enough was received and transfer the ouput to the recipient.
        n = params.output.length;
        for (uint256 i = 0; i < n; i = _increment(i)) {
            uint256 balanceShares = bentoBox.balanceOf(
                params.output[i].token,
                address(this)
            );
            if (balanceShares < params.output[i].minAmount)
                revert TooLittleReceived();
            if (params.output[i].unwrapBento) {
                bentoBox.withdraw(
                    params.output[i].token,
                    address(this),
                    params.output[i].to,
                    0,
                    balanceShares
                );
            } else {
                bentoBox.transfer(
                    params.output[i].token,
                    address(this),
                    params.output[i].to,
                    balanceShares
                );
            }
        }
    }

    function _increment(uint256 i) internal pure returns (uint256) {
        unchecked {
            return i + 1;
        }
    }
}

File 7 of 25 : StargateAdapter.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

import "../interfaces/stargate/IStargateAdapter.sol";

/// @title StargateAdapter
/// @notice Adapter for function used by Stargate Bridge
abstract contract StargateAdapter is ImmutableState, IStargateReceiver {
    using SafeERC20 for IERC20;

    // Custom Error
    error NotStargateRouter();

    // events
    event StargateSushiXSwapSrc(bytes32 indexed srcContext);
    event StargateSushiXSwapDst(bytes32 indexed srcContext, bool failed);

    struct StargateTeleportParams {
        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; // sushiXswap 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
    }

    /// @notice Approves token to the Stargate Router
    /// @param token token to approve
    function approveToStargateRouter(IERC20 token) external {
        token.safeApprove(address(stargateRouter), type(uint256).max);
    }

    /// @notice Bridges the token to dst chain using Stargate Router
    /// @dev It is hardcoded to use all the contract balance. Only call this as the last step.
    /// The refund address for extra fees sent it msg.sender.
    /// @param params required by the Stargate, can be found at StargateTeleportParams struct.
    /// @param actions An array with a sequence of actions to execute (see ACTION_ declarations).
    /// @param values A one-to-one mapped array to `actions`. Native token amount to send along action.
    /// @param datas A one-to-one mapped array to `actions`. Contains abi encoded data of function arguments.
    function _stargateTeleport(
        StargateTeleportParams memory params,
        uint8[] memory actions,
        uint256[] memory values,
        bytes[] memory datas
    ) internal {
        bytes memory payload = abi.encode(params.to, actions, values, datas, params.srcContext);

        stargateRouter.swap{value: address(this).balance}(
            params.dstChainId,
            params.srcPoolId,
            params.dstPoolId,
            payable(msg.sender), // refund address
            params.amount != 0
                ? params.amount
                : IERC20(params.token).balanceOf(address(this)),
            params.amountMin,
            IStargateRouter.lzTxObj(
                params.gas, // extra gas to be sent for dst execution
                params.dustAmount,
                abi.encodePacked(params.receiver)
            ),
            abi.encodePacked(params.receiver), // sushiXswap on the dst chain
            payload
        );

        stargateWidget.partnerSwap(0x0001);

        emit StargateSushiXSwapSrc(params.srcContext);
    }

    /// @notice Get the fees to be paid in native token for the swap
    /// @param _dstChainId stargate dst chainId
    /// @param _functionType stargate Function type 1 for swap.
    /// See more at https://stargateprotocol.gitbook.io/stargate/developers/function-types
    /// @param _receiver sushiXswap on the dst chain
    /// @param _gas extra gas being sent
    /// @param _dustAmount dust amount to be received at the dst chain
    /// @param _payload payload being sent at the dst chain
    function getFee(
        uint16 _dstChainId,
        uint8 _functionType,
        address _receiver,
        uint256 _gas,
        uint256 _dustAmount,
        bytes memory _payload
    ) external view returns (uint256 a, uint256 b) {
        (a, b) = stargateRouter.quoteLayerZeroFee(
            _dstChainId,
            _functionType,
            abi.encodePacked(_receiver),
            abi.encode(_payload),
            IStargateRouter.lzTxObj(
                _gas,
                _dustAmount,
                abi.encodePacked(_receiver)
            )
        );
    }

    /// @notice Receiver function on dst chain
    /// @param _token bridge token received
    /// @param amountLD amount received
    /// @param payload ABI-Encoded data received from src chain
    function sgReceive(
        uint16,
        bytes memory,
        uint256,
        address _token,
        uint256 amountLD,
        bytes memory payload
    ) external override {
        if (msg.sender != address(stargateRouter)) revert NotStargateRouter();

        (
            address to,
            uint8[] memory actions,
            uint256[] memory values,
            bytes[] memory datas,
            bytes32 srcContext
        ) = abi.decode(payload, (address, uint8[], uint256[], bytes[], bytes32));

        // 100000 -> exit gas
        uint256 limit = gasleft() - 200000;
        bool failed;
        /// @dev incase the actions fail, transfer bridge token to the to address
        try
            ISushiXSwap(payable(address(this))).cook{gas: limit}(
                actions,
                values,
                datas
            )
        {} catch (bytes memory) {
            IERC20(_token).safeTransfer(to, amountLD);
            failed = true;
        }

        /// @dev transfer any native token received as dust to the to address
        if (address(this).balance > 0)
            to.call{value: (address(this).balance)}("");

        emit StargateSushiXSwapDst(srcContext, failed);

    }
}

File 8 of 25 : IBentoBoxMinimal.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

/// @notice Minimal BentoBox vault interface.
/// @dev `token` is aliased as `address` from `IERC20` for simplicity.
interface IBentoBoxMinimal {
    /// @notice Balance per ERC-20 token per account in shares.
    function balanceOf(address, address) external view returns (uint256);

    /// @dev Helper function to represent an `amount` of `token` in shares.
    /// @param token The ERC-20 token.
    /// @param amount The `token` amount.
    /// @param roundUp If the result `share` should be rounded up.
    /// @return share The token amount represented in shares.
    function toShare(
        address token,
        uint256 amount,
        bool roundUp
    ) external view returns (uint256 share);

    /// @dev Helper function to represent shares back into the `token` amount.
    /// @param token The ERC-20 token.
    /// @param share The amount of shares.
    /// @param roundUp If the result should be rounded up.
    /// @return amount The share amount back into native representation.
    function toAmount(
        address token,
        uint256 share,
        bool roundUp
    ) external view returns (uint256 amount);

    /// @notice Registers this contract so that users can approve it for BentoBox.
    function registerProtocol() external;

    /// @notice Deposit an amount of `token` represented in either `amount` or `share`.
    /// @param token_ The ERC-20 token to deposit.
    /// @param from which account to pull the tokens.
    /// @param to which account to push the tokens.
    /// @param amount Token amount in native representation to deposit.
    /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.
    /// @return amountOut The amount deposited.
    /// @return shareOut The deposited amount represented in shares.
    function deposit(
        address token_,
        address from,
        address to,
        uint256 amount,
        uint256 share
    ) external payable returns (uint256 amountOut, uint256 shareOut);

    /// @notice Withdraws an amount of `token` from a user account.
    /// @param token_ The ERC-20 token to withdraw.
    /// @param from which user to pull the tokens.
    /// @param to which user to push the tokens.
    /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.
    /// @param share Like above, but `share` takes precedence over `amount`.
    function withdraw(
        address token_,
        address from,
        address to,
        uint256 amount,
        uint256 share
    ) external returns (uint256 amountOut, uint256 shareOut);

    /// @notice Transfer shares from a user account to another one.
    /// @param token The ERC-20 token to transfer.
    /// @param from which user to pull the tokens.
    /// @param to which user to push the tokens.
    /// @param share The amount of `token` in shares.
    function transfer(
        address token,
        address from,
        address to,
        uint256 share
    ) external;

    function setMasterContractApproval(
        address user,
        address masterContract,
        bool approved,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}

File 9 of 25 : ImmutableState.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

import "../interfaces/IImmutableState.sol";

/// @title ImmutableState
/// @notice Stores the immutable state
abstract contract ImmutableState is IImmutableState {
    /// @notice BentoBox token vault
    IBentoBoxMinimal public immutable override bentoBox;

    /// @notice Stargate Router for cross chain interaction
    IStargateRouter public immutable override stargateRouter;

    /// @notice Stargate Widget for stargate partner fee
    IStargateWidget public immutable override stargateWidget;

    /// @notice Sushiswap Legacy AMM Factory
    address public immutable override factory;

    /// @notice Sushiswap Legacy AMM PairCodeHash
    bytes32 public immutable override pairCodeHash;

    constructor(
        IBentoBoxMinimal _bentoBox,
        IStargateRouter _stargateRouter,
        address _factory,
        bytes32 _pairCodeHash,
        IStargateWidget _stargateWidget
    ) {
        bentoBox = _bentoBox;
        stargateRouter = _stargateRouter;
        stargateWidget = _stargateWidget;
        factory = _factory;
        pairCodeHash = _pairCodeHash;
    }
}

File 10 of 25 : IImmutableState.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

import "./IBentoBoxMinimal.sol";
import "./stargate/IStargateRouter.sol";
import "./stargate/IStargateWidget.sol";

interface IImmutableState {
    function bentoBox() external view returns (IBentoBoxMinimal);

    function stargateRouter() external view returns (IStargateRouter);

    function stargateWidget() external view returns (IStargateWidget);

    function factory() external view returns (address);

    function pairCodeHash() external view returns (bytes32);
}

File 11 of 25 : IStargateRouter.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.11;

interface IStargateRouter {

    struct lzTxObj {
        uint256 dstGasForCall;
        uint256 dstNativeAmount;
        bytes dstNativeAddr;
    }

    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 quoteLayerZeroFee(
        uint16 _dstChainId,
        uint8 _functionType,
        bytes calldata _toAddress,
        bytes calldata _transferAndCallPayload,
        lzTxObj memory _lzTxParams
    ) external view returns (uint256, uint256);
}

File 12 of 25 : IStargateWidget.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.11;

interface IStargateWidget {
    function partnerSwap(bytes2 _partnerId) external;
}

File 13 of 25 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.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));
        }
    }

    /**
     * @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");
        }
    }
}

File 14 of 25 : IWETH.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

interface IWETH {
    function deposit() external payable;

    function transfer(address to, uint256 value) external returns (bool);

    function withdraw(uint256) external;
}

File 15 of 25 : IERC20.sol
// 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);
}

File 16 of 25 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.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://diligence.consensys.net/posts/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 functionCall(target, data, "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");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(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) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(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) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason 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 {
            // 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

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 17 of 25 : UniswapV2Library.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.5.0;

import "@sushiswap/core/contracts/uniswapv2/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);
        }
    }
}

File 18 of 25 : IUniswapV2Pair.sol
// 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;
}

File 19 of 25 : SafeMath.sol
// 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");
    }
}

File 20 of 25 : ITridentSwapAdapter.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

import "./ITridentRouter.sol";
import "../../adapters/BentoAdapter.sol";
import "../../adapters/TokenAdapter.sol";
import "../../base/ImmutableState.sol";

interface ITridentSwapAdapter {}

File 21 of 25 : ITridentRouter.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

import "./IPool.sol";
import "../IBentoBoxMinimal.sol";
import "@openzeppelin/contracts/interfaces/IERC20.sol";

/// @notice Trident pool router interface.
interface ITridentRouter {
    struct Path {
        address pool;
        bytes data;
    }

    struct ExactInputSingleParams {
        uint256 amountIn;
        uint256 amountOutMinimum;
        address pool;
        address tokenIn;
        bytes data;
    }

    struct ExactInputParams {
        address tokenIn;
        uint256 amountIn;
        uint256 amountOutMinimum;
        Path[] path;
    }

    struct TokenInput {
        address token;
        bool native;
        uint256 amount;
    }

    struct InitialPath {
        address tokenIn;
        address pool;
        bool native;
        uint256 amount;
        bytes data;
    }

    struct PercentagePath {
        address tokenIn;
        address pool;
        uint64 balancePercentage; // Multiplied by 10^6. 100% = 100_000_000
        bytes data;
    }

    struct Output {
        address token;
        address to;
        bool unwrapBento;
        uint256 minAmount;
    }

    struct ComplexPathParams {
        InitialPath[] initialPath;
        PercentagePath[] percentagePath;
        Output[] output;
    }
}

File 22 of 25 : IPool.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.11;

/// @notice Trident pool interface.
interface IPool {
    /// @notice Executes a swap from one token to another.
    /// @dev The input tokens must've already been sent to the pool.
    /// @param data ABI-encoded params that the pool requires.
    /// @return finalAmountOut The amount of output tokens that were sent to the user.
    function swap(bytes calldata data)
        external
        returns (uint256 finalAmountOut);

    /// @notice Executes a swap from one token to another with a callback.
    /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.
    /// @param data ABI-encoded params that the pool requires.
    /// @return finalAmountOut The amount of output tokens that were sent to the user.
    function flashSwap(bytes calldata data)
        external
        returns (uint256 finalAmountOut);

    /// @notice Mints liquidity tokens.
    /// @param data ABI-encoded params that the pool requires.
    /// @return liquidity The amount of liquidity tokens that were minted for the user.
    function mint(bytes calldata data) external returns (uint256 liquidity);

    /// @notice Burns liquidity tokens.
    /// @dev The input LP tokens must've already been sent to the pool.
    /// @param data ABI-encoded params that the pool requires.
    /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.
    function burn(bytes calldata data)
        external
        returns (TokenAmount[] memory withdrawnAmounts);

    /// @notice Burns liquidity tokens for a single output token.
    /// @dev The input LP tokens must've already been sent to the pool.
    /// @param data ABI-encoded params that the pool requires.
    /// @return amountOut The amount of output tokens that were sent to the user.
    function burnSingle(bytes calldata data)
        external
        returns (uint256 amountOut);

    /// @return A unique identifier for the pool type.
    function poolIdentifier() external pure returns (bytes32);

    /// @return An array of tokens supported by the pool.
    function getAssets() external view returns (address[] memory);

    /// @notice Simulates a trade and returns the expected output.
    /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.
    /// @param data ABI-encoded params that the pool requires.
    /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.
    function getAmountOut(bytes calldata data)
        external
        view
        returns (uint256 finalAmountOut);

    /// @notice Simulates a trade and returns the expected output.
    /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.
    /// @param data ABI-encoded params that the pool requires.
    /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.
    function getAmountIn(bytes calldata data)
        external
        view
        returns (uint256 finalAmountIn);

    /// @dev This event must be emitted on all swaps.
    event Swap(
        address indexed recipient,
        address indexed tokenIn,
        address indexed tokenOut,
        uint256 amountIn,
        uint256 amountOut
    );

    /// @dev This struct frames output tokens for burns.
    struct TokenAmount {
        address token;
        uint256 amount;
    }
}

File 23 of 25 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)

pragma solidity ^0.8.0;

import "../token/ERC20/IERC20.sol";

File 24 of 25 : IStargateAdapter.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.11;

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../../base/ImmutableState.sol";
import "../ISushiXSwap.sol";
import "./IStargateReceiver.sol";
import "./IStargateWidget.sol";

interface IStargateAdapter {}

File 25 of 25 : IStargateReceiver.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.11;

interface IStargateReceiver {
    function sgReceive(
        uint16 _chainId,
        bytes memory _srcAddress,
        uint256 _nonce,
        address _token,
        uint256 amountLD,
        bytes memory payload
    ) external;
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 999999
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IBentoBoxMinimal","name":"_bentoBox","type":"address"},{"internalType":"contract IStargateRouter","name":"_stargateRouter","type":"address"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"bytes32","name":"_pairCodeHash","type":"bytes32"},{"internalType":"contract IStargateWidget","name":"_stargateWidget","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NotStargateRouter","type":"error"},{"inputs":[],"name":"TooLittleReceived","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"srcContext","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"failed","type":"bool"}],"name":"StargateSushiXSwapDst","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"srcContext","type":"bytes32"}],"name":"StargateSushiXSwapSrc","type":"event"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"approveToStargateRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bentoBox","outputs":[{"internalType":"contract IBentoBoxMinimal","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8[]","name":"actions","type":"uint8[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"datas","type":"bytes[]"}],"name":"cook","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_dstChainId","type":"uint16"},{"internalType":"uint8","name":"_functionType","type":"uint8"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_gas","type":"uint256"},{"internalType":"uint256","name":"_dustAmount","type":"uint256"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"getFee","outputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pairCodeHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":[],"name":"stargateRouter","outputs":[{"internalType":"contract IStargateRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stargateWidget","outputs":[{"internalType":"contract IStargateWidget","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

6101206040523480156200001257600080fd5b5060405162004ea038038062004ea08339810160408190526200003591620000d2565b6001600160a01b03808616608081905281861660a05281831660c05290841660e0526101008390526040805163577268d960e11b8152905163aee4d1b29160048082019260009290919082900301818387803b1580156200009557600080fd5b505af1158015620000aa573d6000803e3d6000fd5b50505050505050505062000146565b6001600160a01b0381168114620000cf57600080fd5b50565b600080600080600060a08688031215620000eb57600080fd5b8551620000f881620000b9565b60208701519095506200010b81620000b9565b60408701519094506200011e81620000b9565b6060870151608088015191945092506200013881620000b9565b809150509295509295909350565b60805160a05160c05160e05161010051614c4b6200025560003960008181610194015281816113e1015281816115040152612ca501526000818161022a015281816113be015281816114ad01528181612c3f0152612c8201526000818161016001526125220152600081816101d601528181610ad001528181610c6301528181610e8c01526122c401526000818160cd01528181610352015281816105d2015281816105fd015281816107e601528181610f3701528181611018015281816110e4015281816111ae015281816116d7015281816116fe0152818161173f0152818161196401528181611b7b01528181611cbf01528181611ebf01528181612034015261216b0152614c4b6000f3fe60806040526004361061009a5760003560e01c80639aab924811610069578063ab8236f31161004e578063ab8236f3146101f8578063c45a015514610218578063d1ac35351461024c57600080fd5b80639aab924814610182578063a9e56f3c146101c457600080fd5b8063656f3d64146100a65780636b2ace87146100bb5780636ce4fe03146101195780636f435ac21461014e57600080fd5b366100a157005b600080fd5b6100b96100b436600461386e565b61026c565b005b3480156100c757600080fd5b506100ef7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561012557600080fd5b50610139610134366004613986565b610acb565b60408051928352602083019190915201610110565b34801561015a57600080fd5b506100ef7f000000000000000000000000000000000000000000000000000000000000000081565b34801561018e57600080fd5b506101b67f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610110565b3480156101d057600080fd5b506100ef7f000000000000000000000000000000000000000000000000000000000000000081565b34801561020457600080fd5b506100b9610213366004613a0d565b610c4b565b34801561022457600080fd5b506100ef7f000000000000000000000000000000000000000000000000000000000000000081565b34801561025857600080fd5b506100b9610267366004613a9d565b610e70565b825160005b81811015610ac457600085828151811061028d5761028d613aba565b60200260200101519050600060ff168160ff1614156103ba5760008060008060008887815181106102c0576102c0613aba565b60200260200101518060200190518101906102db9190613b09565b6040517fc0a47c9300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152306024830152851515604483015260ff851660648301526084820184905260a48201839052959a50939850919650945092507f00000000000000000000000000000000000000000000000000000000000000009091169063c0a47c939060c401600060405180830381600087803b15801561039857600080fd5b505af11580156103ac573d6000803e3d6000fd5b505050505050505050610abb565b60ff811660011415610431576000806000808786815181106103de576103de613aba565b60200260200101518060200190518101906103f99190613b63565b935093509350935061042884338585858e8c8151811061041b5761041b613aba565b6020026020010151610ed4565b50505050610abb565b60ff81166002141561049457600080600080600088878151811061045757610457613aba565b60200260200101518060200190518101906104729190613bab565b9450945094509450945061048a853386868686610faf565b5050505050610abb565b60ff8116600b14156104eb5760008060008685815181106104b7576104b7613aba565b60200260200101518060200190518101906104d29190613c08565b9250925092506104e3838383611213565b505050610abb565b60ff8116600314156106315760008060008087868151811061050f5761050f613aba565b602002602001015180602001905181019061052a9190613b63565b935093509350935081600014156105cc576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa1580156105a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c99190613c4b565b91505b6105f7847f00000000000000000000000000000000000000000000000000000000000000008461123a565b610428847f00000000000000000000000000000000000000000000000000000000000000008585858e8c8151811061041b5761041b613aba565b60ff81166004141561073d57600080600086858151811061065457610654613aba565b602002602001015180602001905181019061066f9190613c08565b92509250925080600014156107325773ffffffffffffffffffffffffffffffffffffffff83161561072f576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610704573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107289190613c4b565b9050610732565b50475b6104e383838361123a565b60ff81166005141561086257600080600080600088878151811061076357610763613aba565b602002602001015180602001905181019061077e9190613bab565b94509450945094509450826000148015610796575081155b15610854576040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa15801561082d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108519190613c4b565b91505b61048a853086868686610faf565b60ff8116600614156108b35760008085848151811061088357610883613aba565b602002602001015180602001905181019061089e9190613c64565b915091506108ac82826112c0565b5050610abb565b60ff8116600714156109d1576000806000808786815181106108d7576108d7613aba565b60200260200101518060200190518101906108f29190613c9e565b9350935093509350600084600014156109b9578260008151811061091857610918613aba565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561098e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b29190613c4b565b9450600190505b6109c685858585856113b6565b505050505050610abb565b60ff811660081415610a175760008483815181106109f1576109f1613aba565b6020026020010151806020019051810190610a0c9190613dd7565b90506108ac8161162a565b60ff811660091415610a63576000848381518110610a3757610a37613aba565b6020026020010151806020019051810190610a529190614104565b9050610a5d81611954565b50610abb565b60ff8116600a1415610abb57600080600080878681518110610a8757610a87613aba565b6020026020010151806020019051810190610aa29190614401565b9350935093509350610ab68484848461228c565b505050505b50600101610271565b5050505050565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630a512369898989604051602001610b48919060609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b60405160208183030381529060405287604051602001610b68919061457f565b60405160208183030381529060405260405180606001604052808c81526020018b81526020018d604051602001610bca919060609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b6040516020818303038152906040528152506040518663ffffffff1660e01b8152600401610bfc9594939291906145bb565b6040805180830381865afa158015610c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3c9190614613565b90999098509650505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610cba576040517f8c66bf5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600080600085806020019051810190610cd69190614637565b94509450945094509450600062030d405a610cf1919061470c565b6040517f656f3d64000000000000000000000000000000000000000000000000000000008152909150600090309063656f3d64908490610d39908a908a908a90600401614807565b600060405180830381600088803b158015610d5357600080fd5b5087f193505050508015610d65575060015b610dc0573d808015610d93576040519150601f19603f3d011682016040523d82523d6000602084013e610d98565b606091505b50610dba73ffffffffffffffffffffffffffffffffffffffff8c16898c6125cd565b60019150505b4715610e255760405173ffffffffffffffffffffffffffffffffffffffff8816904790600081818185875af1925050503d8060008114610e1c576040519150601f19603f3d011682016040523d82523d6000602084013e610e21565b606091505b5050505b827fd02bbeba90c0a3636769d1b8c9f07e2b5e4131b8fbcc2d6ba56054e20b98d75d82604051610e59911515815260200190565b60405180910390a250505050505050505050505050565b610ed173ffffffffffffffffffffffffffffffffffffffff82167f00000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6126a1565b50565b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301528681166024830152858116604483015260648201859052608482018490527f000000000000000000000000000000000000000000000000000000000000000016906302b9446c90839060a401604080518083038185885af1158015610f80573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610fa59190614613565b5050505050505050565b801561108b576040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301528681166024830152858116604483015260648201859052608482018490527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015611060573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110849190614613565b505061120b565b8215611152576040517fda5139ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015260248201859052600060448301527f0000000000000000000000000000000000000000000000000000000000000000169063da5139ca90606401602060405180830381865afa15801561112b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114f9190613c4b565b91505b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015286811660248301528581166044830152606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b1580156111f257600080fd5b505af1158015611206573d6000803e3d6000fd5b505050505b505050505050565b61123573ffffffffffffffffffffffffffffffffffffffff8416338484612823565b505050565b73ffffffffffffffffffffffffffffffffffffffff8316156112775761123573ffffffffffffffffffffffffffffffffffffffff841683836125cd565b60405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f193505050501580156112ba573d6000803e3d6000fd5b50505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff831690632e1a7d4d9082906370a0823190602401602060405180830381865afa158015611332573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113569190613c4b565b6040518263ffffffff1660e01b815260040161137491815260200190565b600060405180830381600087803b15801561138e57600080fd5b505af11580156113a2573d6000803e3d6000fd5b505050506113b26000824761123a565b5050565b6000806114057f000000000000000000000000000000000000000000000000000000000000000088877f0000000000000000000000000000000000000000000000000000000000000000612881565b90508060018251611416919061470c565b8151811061142657611426613aba565b602002602001015191508582101561149f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f696e73756666696369656e742d616d6f756e742d6f757400000000000000000060448201526064015b60405180910390fd5b8215611615576116156115287f0000000000000000000000000000000000000000000000000000000000000000876000815181106114df576114df613aba565b6020026020010151886001815181106114fa576114fa613aba565b60200260200101517f0000000000000000000000000000000000000000000000000000000000000000612a28565b8660008151811061153b5761153b613aba565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa1580156115b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d59190613c4b565b876000815181106115e8576115e8613aba565b602002602001015173ffffffffffffffffffffffffffffffffffffffff166125cd9092919063ffffffff16565b611620818686612b42565b5095945050505050565b60008160200151600014156118365781516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156116a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cb9190613c4b565b90506116fc83600001517f00000000000000000000000000000000000000000000000000000000000000008361123a565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166302b9446c84600001517f0000000000000000000000000000000000000000000000000000000000000000866060015160008151811061177557611775613aba565b6020908102919091010151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529183166024830152919091166044820152606481018490526000608482015260a40160408051808303816000875af115801561180a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182e9190614613565b602085015250505b60608201515160005b8181101561190f578360600151818151811061185d5761185d613aba565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1663627dd56a8560600151838151811061189a5761189a613aba565b6020026020010151602001516040518263ffffffff1660e01b81526004016118c2919061457f565b6020604051808303816000875af11580156118e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119059190613c4b565b925060010161183f565b50826040015182101561194e576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50919050565b80515160005b81811015611b64577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f18d03cc846000015183815181106119b4576119b4613aba565b60200260200101516000015130866000015185815181106119d7576119d7613aba565b602002602001015160200151876000015186815181106119f9576119f9613aba565b6020908102919091010151606001516040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b16815273ffffffffffffffffffffffffffffffffffffffff94851660048201529284166024840152921660448201526064810191909152608401600060405180830381600087803b158015611a8557600080fd5b505af1158015611a99573d6000803e3d6000fd5b5050505082600001518181518110611ab357611ab3613aba565b60200260200101516020015173ffffffffffffffffffffffffffffffffffffffff1663627dd56a84600001518381518110611af057611af0613aba565b6020026020010151608001516040518263ffffffff1660e01b8152600401611b18919061457f565b6020604051808303816000875af1158015611b37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5b9190613c4b565b5060010161195a565b505060208101515160005b81811015611ea85760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f7888aec85602001518481518110611bcb57611bcb613aba565b6020908102919091010151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152306024820152604401602060405180830381865afa158015611c46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6a9190613c4b565b90506000611c7a6008600a61496a565b85602001518481518110611c9057611c90613aba565b60200260200101516040015167ffffffffffffffff1683611cb19190614979565b611cbb91906149b6565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f18d03cc86602001518581518110611d0f57611d0f613aba565b6020026020010151600001513088602001518781518110611d3257611d32613aba565b60209081029190910181015101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff9384166004820152918316602483015291909116604482015260648101849052608401600060405180830381600087803b158015611dbe57600080fd5b505af1158015611dd2573d6000803e3d6000fd5b5050505084602001518381518110611dec57611dec613aba565b60200260200101516020015173ffffffffffffffffffffffffffffffffffffffff1663627dd56a86602001518581518110611e2957611e29613aba565b6020026020010151606001516040518263ffffffff1660e01b8152600401611e51919061457f565b6020604051808303816000875af1158015611e70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e949190613c4b565b505050611ea18160010190565b9050611b6f565b505060408101515160005b818110156112355760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f7888aec85604001518481518110611f0f57611f0f613aba565b6020908102919091010151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152306024820152604401602060405180830381865afa158015611f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fae9190613c4b565b905083604001518281518110611fc657611fc6613aba565b60200260200101516060015181101561200b576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360400151828151811061202157612021613aba565b60200260200101516040015115612169577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166397da6d308560400151848151811061208457612084613aba565b60200260200101516000015130876040015186815181106120a7576120a7613aba565b60209081029190910181015101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529183166024830152919091166044820152600060648201526084810184905260a40160408051808303816000875af115801561213e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121629190614613565b5050612283565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663f18d03cc856040015184815181106121bb576121bb613aba565b60200260200101516000015130876040015186815181106121de576121de613aba565b60209081029190910181015101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff9384166004820152918316602483015291909116604482015260648101849052608401600060405180830381600087803b15801561226a57600080fd5b505af115801561227e573d6000803e3d6000fd5b505050505b50600101611eb3565b60008461010001518484848861014001516040516020016122b19594939291906149f1565b60405160208183030381529060405290507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639fbf10fc47876000015188604001518960600151338b60800151600014156123b55760208c01516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561238c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b09190613c4b565b6123bb565b8b608001515b8c60a0015160405180606001604052808f610120015181526020018f60c0015181526020018f60e00151604051602001612420919060609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b6040516020818303038152906040528152508e60e00151604051602001612472919060609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b6040516020818303038152906040528b6040518b63ffffffff1660e01b81526004016124a699989796959493929190614a59565b6000604051808303818588803b1580156124bf57600080fd5b505af11580156124d3573d6000803e3d6000fd5b50506040517fa87376e90000000000000000000000000000000000000000000000000000000081527e0100000000000000000000000000000000000000000000000000000000000060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16935063a87376e992506024019050600060405180830381600087803b15801561257f57600080fd5b505af1158015612593573d6000803e3d6000fd5b505050506101408501516040517fef89f27cad105cfe7c63f4a5c70e6b1392b571ff544a83de4bf71ceb46bacfee90600090a25050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112359084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612d7f565b80158061274157506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa15801561271b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273f9190613c4b565b155b6127cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401611496565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112359084907f095ea7b3000000000000000000000000000000000000000000000000000000009060640161261f565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526112ba9085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161261f565b60606002835110156128ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f556e697377617056324c6962726172793a20494e56414c49445f5041544800006044820152606401611496565b825167ffffffffffffffff81111561290957612909613585565b604051908082528060200260200182016040528015612932578160200160208202803683370190505b509050838160008151811061294957612949613aba565b60200260200101818152505060005b60018451612966919061470c565b811015612a1f576000806129ba8887858151811061298657612986613aba565b60200260200101518886600161299c9190614ae4565b815181106129ac576129ac613aba565b602002602001015188612e8b565b915091506129e28484815181106129d3576129d3613aba565b60200260200101518383612f8c565b846129ee856001614ae4565b815181106129fe576129fe613aba565b60200260200101818152505050508080612a1790614afc565b915050612958565b50949350505050565b6000806000612a378686613106565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084811b8216602084015283901b166034820152919350915087906048016040516020818303038152906040528051906020012085604051602001612b01939291907fff00000000000000000000000000000000000000000000000000000000000000815260609390931b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830191909152603582015260550190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120979650505050505050565b60005b60018351612b53919061470c565b8110156112ba57600080848381518110612b6f57612b6f613aba565b602002602001015185846001612b859190614ae4565b81518110612b9557612b95613aba565b6020026020010151915091506000612bad8383613106565b509050600087612bbe866001614ae4565b81518110612bce57612bce613aba565b602002602001015190506000808373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614612c1657826000612c1a565b6000835b91509150600060028a51612c2e919061470c565b8810612c3a5788612c7b565b612c7b7f0000000000000000000000000000000000000000000000000000000000000000878c612c6b8c6002614ae4565b815181106114fa576114fa613aba565b9050612cc97f000000000000000000000000000000000000000000000000000000000000000088887f0000000000000000000000000000000000000000000000000000000000000000612a28565b73ffffffffffffffffffffffffffffffffffffffff1663022c0d9f84848460006040519080825280601f01601f191660200182016040528015612d13576020820181803683370190505b506040518563ffffffff1660e01b8152600401612d339493929190614b35565b600060405180830381600087803b158015612d4d57600080fd5b505af1158015612d61573d6000803e3d6000fd5b50505050505050505050508080612d7790614afc565b915050612b45565b6000612de1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661328b9092919063ffffffff16565b8051909150156112355780806020019051810190612dff9190614b70565b611235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611496565b6000806000612e9a8686613106565b509050600080612eac89898989612a28565b73ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015612ef6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1a9190614ba9565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691508273ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614612f79578082612f7c565b81815b909a909950975050505050505050565b600080841161301d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4960448201527f4e5055545f414d4f554e540000000000000000000000000000000000000000006064820152608401611496565b60008311801561302d5750600082115b6130b9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4c60448201527f49515549444954590000000000000000000000000000000000000000000000006064820152608401611496565b60006130c7856103e56132a4565b905060006130d582856132a4565b905060006130ef836130e9886103e86132a4565b90613334565b90506130fb81836149b6565b979650505050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156131c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f556e697377617056324c6962726172793a204944454e544943414c5f4144445260448201527f45535345530000000000000000000000000000000000000000000000000000006064820152608401611496565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16106131ff578284613202565b83835b909250905073ffffffffffffffffffffffffffffffffffffffff8216613284576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f556e697377617056324c6962726172793a205a45524f5f4144445245535300006044820152606401611496565b9250929050565b606061329a84846000856133ac565b90505b9392505050565b60008115806132c8575082826132ba8183614979565b92506132c690836149b6565b145b61332e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f770000000000000000000000006044820152606401611496565b92915050565b6000826133418382614ae4565b915081101561332e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f770000000000000000000000006044820152606401611496565b60608247101561343e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611496565b73ffffffffffffffffffffffffffffffffffffffff85163b6134bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611496565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516134e59190614bf9565b60006040518083038185875af1925050503d8060008114613522576040519150601f19603f3d011682016040523d82523d6000602084013e613527565b606091505b50915091506130fb8282866060831561354157508161329d565b8251156135515782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611496919061457f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff811182821017156135d7576135d7613585565b60405290565b6040805190810167ffffffffffffffff811182821017156135d7576135d7613585565b6040516060810167ffffffffffffffff811182821017156135d7576135d7613585565b60405160a0810167ffffffffffffffff811182821017156135d7576135d7613585565b604051610160810167ffffffffffffffff811182821017156135d7576135d7613585565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156136b1576136b1613585565b604052919050565b600067ffffffffffffffff8211156136d3576136d3613585565b5060051b60200190565b60ff81168114610ed157600080fd5b600082601f8301126136fd57600080fd5b8135602061371261370d836136b9565b61366a565b82815260059290921b8401810191818101908684111561373157600080fd5b8286015b8481101561374c5780358352918301918301613735565b509695505050505050565b600067ffffffffffffffff82111561377157613771613585565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f8301126137ae57600080fd5b81356137bc61370d82613757565b8181528460208386010111156137d157600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f8301126137ff57600080fd5b8135602061380f61370d836136b9565b82815260059290921b8401810191818101908684111561382e57600080fd5b8286015b8481101561374c57803567ffffffffffffffff8111156138525760008081fd5b6138608986838b010161379d565b845250918301918301613832565b60008060006060848603121561388357600080fd5b833567ffffffffffffffff8082111561389b57600080fd5b818601915086601f8301126138af57600080fd5b813560206138bf61370d836136b9565b82815260059290921b8401810191818101908a8411156138de57600080fd5b948201945b838610156139055785356138f6816136dd565b825294820194908201906138e3565b9750508701359250508082111561391b57600080fd5b613927878388016136ec565b9350604086013591508082111561393d57600080fd5b5061394a868287016137ee565b9150509250925092565b61ffff81168114610ed157600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114610ed157600080fd5b60008060008060008060c0878903121561399f57600080fd5b86356139aa81613954565b955060208701356139ba816136dd565b945060408701356139ca81613964565b9350606087013592506080870135915060a087013567ffffffffffffffff8111156139f457600080fd5b613a0089828a0161379d565b9150509295509295509295565b60008060008060008060c08789031215613a2657600080fd5b8635613a3181613954565b9550602087013567ffffffffffffffff80821115613a4e57600080fd5b613a5a8a838b0161379d565b96506040890135955060608901359150613a7382613964565b9093506080880135925060a08801359080821115613a9057600080fd5b50613a0089828a0161379d565b600060208284031215613aaf57600080fd5b813561329d81613964565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8051613af481613964565b919050565b80518015158114613af457600080fd5b600080600080600060a08688031215613b2157600080fd5b8551613b2c81613964565b9450613b3a60208701613af9565b93506040860151613b4a816136dd565b6060870151608090970151959894975095949392505050565b60008060008060808587031215613b7957600080fd5b8451613b8481613964565b6020860151909450613b9581613964565b6040860151606090960151949790965092505050565b600080600080600060a08688031215613bc357600080fd5b8551613bce81613964565b6020870151909550613bdf81613964565b6040870151606088015191955093509150613bfc60808701613af9565b90509295509295909350565b600080600060608486031215613c1d57600080fd5b8351613c2881613964565b6020850151909350613c3981613964565b80925050604084015190509250925092565b600060208284031215613c5d57600080fd5b5051919050565b60008060408385031215613c7757600080fd5b8251613c8281613964565b6020840151909250613c9381613964565b809150509250929050565b60008060008060808587031215613cb457600080fd5b845193506020808601519350604086015167ffffffffffffffff811115613cda57600080fd5b8601601f81018813613ceb57600080fd5b8051613cf961370d826136b9565b81815260059190911b8201830190838101908a831115613d1857600080fd5b928401925b82841015613d3f578351613d3081613964565b82529284019290840190613d1d565b8096505050505050613d5360608601613ae9565b905092959194509250565b60005b83811015613d79578181015183820152602001613d61565b838111156112ba5750506000910152565b600082601f830112613d9b57600080fd5b8151613da961370d82613757565b818152846020838601011115613dbe57600080fd5b613dcf826020830160208701613d5e565b949350505050565b60006020808385031215613dea57600080fd5b825167ffffffffffffffff80821115613e0257600080fd5b9084019060808287031215613e1657600080fd5b613e1e6135b4565b8251613e2981613964565b8152828401518482015260408084015181830152606084015183811115613e4f57600080fd5b80850194505087601f850112613e6457600080fd5b8351613e7261370d826136b9565b81815260059190911b8501860190868101908a831115613e9157600080fd5b8787015b83811015613f2b57805187811115613ead5760008081fd5b8801808d037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001861315613ee15760008081fd5b613ee96135dd565b8a820151613ef681613964565b81528187015189811115613f0a5760008081fd5b613f188f8d83860101613d8a565b828d015250845250918801918801613e95565b506060850152509198975050505050505050565b600082601f830112613f5057600080fd5b81516020613f6061370d836136b9565b82815260059290921b84018101918181019086841115613f7f57600080fd5b8286015b8481101561374c57805167ffffffffffffffff80821115613fa45760008081fd5b81890191506080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215613fdd5760008081fd5b613fe56135b4565b87840151613ff281613964565b815260408481015161400381613964565b828a0152606085810151858116811461401c5760008081fd5b8383015292850151928484111561403557600091508182fd5b6140438e8b86890101613d8a565b90830152508652505050918301918301613f83565b600082601f83011261406957600080fd5b8151602061407961370d836136b9565b82815260079290921b8401810191818101908684111561409857600080fd5b8286015b8481101561374c57608081890312156140b55760008081fd5b6140bd6135b4565b81516140c881613964565b8152818501516140d781613964565b8186015260406140e8838201613af9565b908201526060828101519082015283529183019160800161409c565b6000602080838503121561411757600080fd5b825167ffffffffffffffff8082111561412f57600080fd5b908401906060828703121561414357600080fd5b61414b613600565b82518281111561415a57600080fd5b8301601f8101881361416b57600080fd5b805161417961370d826136b9565b81815260059190911b8201860190868101908a83111561419857600080fd5b8784015b83811015614260578051878111156141b357600080fd5b850160a0818e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00112156141e757600080fd5b6141ef613623565b8a8201516141fc81613964565b8152604082015161420c81613964565b818c015261421c60608301613af9565b60408201526080820151606082015260a08201518981111561423e5760008081fd5b61424c8f8d83860101613d8a565b60808301525084525091880191880161419c565b508452505050828401518281111561427757600080fd5b61428388828601613f3f565b8583015250604083015193508184111561429c57600080fd5b6142a887858501614058565b60408201529695505050505050565b8051613af481613954565b600082601f8301126142d357600080fd5b815160206142e361370d836136b9565b82815260059290921b8401810191818101908684111561430257600080fd5b8286015b8481101561374c578051614319816136dd565b8352918301918301614306565b600082601f83011261433757600080fd5b8151602061434761370d836136b9565b82815260059290921b8401810191818101908684111561436657600080fd5b8286015b8481101561374c578051835291830191830161436a565b600082601f83011261439257600080fd5b815160206143a261370d836136b9565b82815260059290921b840181019181810190868411156143c157600080fd5b8286015b8481101561374c57805167ffffffffffffffff8111156143e55760008081fd5b6143f38986838b0101613d8a565b8452509183019183016143c5565b6000806000808486036101c081121561441957600080fd5b6101608082121561442957600080fd5b614431613646565b915061443c876142b7565b825261444a60208801613ae9565b602083015260408701516040830152606087015160608301526080870151608083015260a087015160a083015260c087015160c083015261448d60e08801613ae9565b60e08301526101006144a0818901613ae9565b908301526101208781015190830152610140808801519083015286015190945067ffffffffffffffff808211156144d657600080fd5b6144e2888389016142c2565b94506101808701519150808211156144f957600080fd5b61450588838901614326565b93506101a087015191508082111561451c57600080fd5b5061452987828801614381565b91505092959194509250565b6000815180845261454d816020860160208601613d5e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061329d6020830184614535565b80518252602081015160208301526000604082015160606040850152613dcf6060850182614535565b61ffff8616815260ff8516602082015260a0604082015260006145e160a0830186614535565b82810360608401526145f38186614535565b905082810360808401526146078185614592565b98975050505050505050565b6000806040838503121561462657600080fd5b505080516020909101519092909150565b600080600080600060a0868803121561464f57600080fd5b855161465a81613964565b602087015190955067ffffffffffffffff8082111561467857600080fd5b61468489838a016142c2565b9550604088015191508082111561469a57600080fd5b6146a689838a01614326565b945060608801519150808211156146bc57600080fd5b506146c988828901614381565b925050608086015190509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561471e5761471e6146dd565b500390565b600081518084526020808501945080840160005b8381101561475657815160ff1687529582019590820190600101614737565b509495945050505050565b600081518084526020808501945080840160005b8381101561475657815187529582019590820190600101614775565b600082825180855260208086019550808260051b84010181860160005b848110156147fa577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08684030189526147e8838351614535565b988401989250908301906001016147ae565b5090979650505050505050565b60608152600061481a6060830186614723565b828103602084015261482c8186614761565b905082810360408401526148408185614791565b9695505050505050565b600181815b808511156148a357817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115614889576148896146dd565b8085161561489657918102915b93841c939080029061484f565b509250929050565b6000826148ba5750600161332e565b816148c75750600061332e565b81600181146148dd57600281146148e757614903565b600191505061332e565b60ff8411156148f8576148f86146dd565b50506001821b61332e565b5060208310610133831016604e8410600b8410161715614926575081810a61332e565b614930838361484a565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115614962576149626146dd565b029392505050565b600061329d60ff8416836148ab565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156149b1576149b16146dd565b500290565b6000826149ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b73ffffffffffffffffffffffffffffffffffffffff8616815260a060208201526000614a2060a0830187614723565b8281036040840152614a328187614761565b90508281036060840152614a468186614791565b9150508260808301529695505050505050565b600061012061ffff8c1683528a602084015289604084015273ffffffffffffffffffffffffffffffffffffffff891660608401528760808401528660a08401528060c0840152614aab81840187614592565b905082810360e0840152614abf8186614535565b9050828103610100840152614ad48185614535565b9c9b505050505050505050505050565b60008219821115614af757614af76146dd565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614b2e57614b2e6146dd565b5060010190565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006148406080830184614535565b600060208284031215614b8257600080fd5b61329d82613af9565b80516dffffffffffffffffffffffffffff81168114613af457600080fd5b600080600060608486031215614bbe57600080fd5b614bc784614b8b565b9250614bd560208501614b8b565b9150604084015163ffffffff81168114614bee57600080fd5b809150509250925092565b60008251614c0b818460208701613d5e565b919091019291505056fea26469706673582212200eb89d099dfbd48538588aed7bd5e9992174fa244f34fb820dbfbac72d39d98d64736f6c634300080b00330000000000000000000000000711b6026068f736bae6b213031fce978d48e02600000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4e18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c63030000000000000000000000000cff9acef65a64b5d76e83b70787b27f7416644c

Deployed Bytecode

0x60806040526004361061009a5760003560e01c80639aab924811610069578063ab8236f31161004e578063ab8236f3146101f8578063c45a015514610218578063d1ac35351461024c57600080fd5b80639aab924814610182578063a9e56f3c146101c457600080fd5b8063656f3d64146100a65780636b2ace87146100bb5780636ce4fe03146101195780636f435ac21461014e57600080fd5b366100a157005b600080fd5b6100b96100b436600461386e565b61026c565b005b3480156100c757600080fd5b506100ef7f0000000000000000000000000711b6026068f736bae6b213031fce978d48e02681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b34801561012557600080fd5b50610139610134366004613986565b610acb565b60408051928352602083019190915201610110565b34801561015a57600080fd5b506100ef7f0000000000000000000000000cff9acef65a64b5d76e83b70787b27f7416644c81565b34801561018e57600080fd5b506101b67fe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c630381565b604051908152602001610110565b3480156101d057600080fd5b506100ef7f00000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd81565b34801561020457600080fd5b506100b9610213366004613a0d565b610c4b565b34801561022457600080fd5b506100ef7f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c481565b34801561025857600080fd5b506100b9610267366004613a9d565b610e70565b825160005b81811015610ac457600085828151811061028d5761028d613aba565b60200260200101519050600060ff168160ff1614156103ba5760008060008060008887815181106102c0576102c0613aba565b60200260200101518060200190518101906102db9190613b09565b6040517fc0a47c9300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152306024830152851515604483015260ff851660648301526084820184905260a48201839052959a50939850919650945092507f0000000000000000000000000711b6026068f736bae6b213031fce978d48e0269091169063c0a47c939060c401600060405180830381600087803b15801561039857600080fd5b505af11580156103ac573d6000803e3d6000fd5b505050505050505050610abb565b60ff811660011415610431576000806000808786815181106103de576103de613aba565b60200260200101518060200190518101906103f99190613b63565b935093509350935061042884338585858e8c8151811061041b5761041b613aba565b6020026020010151610ed4565b50505050610abb565b60ff81166002141561049457600080600080600088878151811061045757610457613aba565b60200260200101518060200190518101906104729190613bab565b9450945094509450945061048a853386868686610faf565b5050505050610abb565b60ff8116600b14156104eb5760008060008685815181106104b7576104b7613aba565b60200260200101518060200190518101906104d29190613c08565b9250925092506104e3838383611213565b505050610abb565b60ff8116600314156106315760008060008087868151811061050f5761050f613aba565b602002602001015180602001905181019061052a9190613b63565b935093509350935081600014156105cc576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa1580156105a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c99190613c4b565b91505b6105f7847f0000000000000000000000000711b6026068f736bae6b213031fce978d48e0268461123a565b610428847f0000000000000000000000000711b6026068f736bae6b213031fce978d48e0268585858e8c8151811061041b5761041b613aba565b60ff81166004141561073d57600080600086858151811061065457610654613aba565b602002602001015180602001905181019061066f9190613c08565b92509250925080600014156107325773ffffffffffffffffffffffffffffffffffffffff83161561072f576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610704573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107289190613c4b565b9050610732565b50475b6104e383838361123a565b60ff81166005141561086257600080600080600088878151811061076357610763613aba565b602002602001015180602001905181019061077e9190613bab565b94509450945094509450826000148015610796575081155b15610854576040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301523060248301527f0000000000000000000000000711b6026068f736bae6b213031fce978d48e026169063f7888aec90604401602060405180830381865afa15801561082d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108519190613c4b565b91505b61048a853086868686610faf565b60ff8116600614156108b35760008085848151811061088357610883613aba565b602002602001015180602001905181019061089e9190613c64565b915091506108ac82826112c0565b5050610abb565b60ff8116600714156109d1576000806000808786815181106108d7576108d7613aba565b60200260200101518060200190518101906108f29190613c9e565b9350935093509350600084600014156109b9578260008151811061091857610918613aba565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561098e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b29190613c4b565b9450600190505b6109c685858585856113b6565b505050505050610abb565b60ff811660081415610a175760008483815181106109f1576109f1613aba565b6020026020010151806020019051810190610a0c9190613dd7565b90506108ac8161162a565b60ff811660091415610a63576000848381518110610a3757610a37613aba565b6020026020010151806020019051810190610a529190614104565b9050610a5d81611954565b50610abb565b60ff8116600a1415610abb57600080600080878681518110610a8757610a87613aba565b6020026020010151806020019051810190610aa29190614401565b9350935093509350610ab68484848461228c565b505050505b50600101610271565b5050505050565b6000807f00000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd73ffffffffffffffffffffffffffffffffffffffff16630a512369898989604051602001610b48919060609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b60405160208183030381529060405287604051602001610b68919061457f565b60405160208183030381529060405260405180606001604052808c81526020018b81526020018d604051602001610bca919060609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b6040516020818303038152906040528152506040518663ffffffff1660e01b8152600401610bfc9594939291906145bb565b6040805180830381865afa158015610c18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3c9190614613565b90999098509650505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd1614610cba576040517f8c66bf5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600080600085806020019051810190610cd69190614637565b94509450945094509450600062030d405a610cf1919061470c565b6040517f656f3d64000000000000000000000000000000000000000000000000000000008152909150600090309063656f3d64908490610d39908a908a908a90600401614807565b600060405180830381600088803b158015610d5357600080fd5b5087f193505050508015610d65575060015b610dc0573d808015610d93576040519150601f19603f3d011682016040523d82523d6000602084013e610d98565b606091505b50610dba73ffffffffffffffffffffffffffffffffffffffff8c16898c6125cd565b60019150505b4715610e255760405173ffffffffffffffffffffffffffffffffffffffff8816904790600081818185875af1925050503d8060008114610e1c576040519150601f19603f3d011682016040523d82523d6000602084013e610e21565b606091505b5050505b827fd02bbeba90c0a3636769d1b8c9f07e2b5e4131b8fbcc2d6ba56054e20b98d75d82604051610e59911515815260200190565b60405180910390a250505050505050505050505050565b610ed173ffffffffffffffffffffffffffffffffffffffff82167f00000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6126a1565b50565b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301528681166024830152858116604483015260648201859052608482018490527f0000000000000000000000000711b6026068f736bae6b213031fce978d48e02616906302b9446c90839060a401604080518083038185885af1158015610f80573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610fa59190614613565b5050505050505050565b801561108b576040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87811660048301528681166024830152858116604483015260648201859052608482018490527f0000000000000000000000000711b6026068f736bae6b213031fce978d48e02616906397da6d309060a40160408051808303816000875af1158015611060573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110849190614613565b505061120b565b8215611152576040517fda5139ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015260248201859052600060448301527f0000000000000000000000000711b6026068f736bae6b213031fce978d48e026169063da5139ca90606401602060405180830381865afa15801561112b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061114f9190613c4b565b91505b6040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff878116600483015286811660248301528581166044830152606482018490527f0000000000000000000000000711b6026068f736bae6b213031fce978d48e026169063f18d03cc90608401600060405180830381600087803b1580156111f257600080fd5b505af1158015611206573d6000803e3d6000fd5b505050505b505050505050565b61123573ffffffffffffffffffffffffffffffffffffffff8416338484612823565b505050565b73ffffffffffffffffffffffffffffffffffffffff8316156112775761123573ffffffffffffffffffffffffffffffffffffffff841683836125cd565b60405173ffffffffffffffffffffffffffffffffffffffff83169082156108fc029083906000818181858888f193505050501580156112ba573d6000803e3d6000fd5b50505050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff831690632e1a7d4d9082906370a0823190602401602060405180830381865afa158015611332573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113569190613c4b565b6040518263ffffffff1660e01b815260040161137491815260200190565b600060405180830381600087803b15801561138e57600080fd5b505af11580156113a2573d6000803e3d6000fd5b505050506113b26000824761123a565b5050565b6000806114057f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c488877fe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303612881565b90508060018251611416919061470c565b8151811061142657611426613aba565b602002602001015191508582101561149f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f696e73756666696369656e742d616d6f756e742d6f757400000000000000000060448201526064015b60405180910390fd5b8215611615576116156115287f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4876000815181106114df576114df613aba565b6020026020010151886001815181106114fa576114fa613aba565b60200260200101517fe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303612a28565b8660008151811061153b5761153b613aba565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa1580156115b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d59190613c4b565b876000815181106115e8576115e8613aba565b602002602001015173ffffffffffffffffffffffffffffffffffffffff166125cd9092919063ffffffff16565b611620818686612b42565b5095945050505050565b60008160200151600014156118365781516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156116a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116cb9190613c4b565b90506116fc83600001517f0000000000000000000000000711b6026068f736bae6b213031fce978d48e0268361123a565b7f0000000000000000000000000711b6026068f736bae6b213031fce978d48e02673ffffffffffffffffffffffffffffffffffffffff166302b9446c84600001517f0000000000000000000000000711b6026068f736bae6b213031fce978d48e026866060015160008151811061177557611775613aba565b6020908102919091010151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529183166024830152919091166044820152606481018490526000608482015260a40160408051808303816000875af115801561180a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061182e9190614613565b602085015250505b60608201515160005b8181101561190f578360600151818151811061185d5761185d613aba565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1663627dd56a8560600151838151811061189a5761189a613aba565b6020026020010151602001516040518263ffffffff1660e01b81526004016118c2919061457f565b6020604051808303816000875af11580156118e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119059190613c4b565b925060010161183f565b50826040015182101561194e576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50919050565b80515160005b81811015611b64577f0000000000000000000000000711b6026068f736bae6b213031fce978d48e02673ffffffffffffffffffffffffffffffffffffffff1663f18d03cc846000015183815181106119b4576119b4613aba565b60200260200101516000015130866000015185815181106119d7576119d7613aba565b602002602001015160200151876000015186815181106119f9576119f9613aba565b6020908102919091010151606001516040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b16815273ffffffffffffffffffffffffffffffffffffffff94851660048201529284166024840152921660448201526064810191909152608401600060405180830381600087803b158015611a8557600080fd5b505af1158015611a99573d6000803e3d6000fd5b5050505082600001518181518110611ab357611ab3613aba565b60200260200101516020015173ffffffffffffffffffffffffffffffffffffffff1663627dd56a84600001518381518110611af057611af0613aba565b6020026020010151608001516040518263ffffffff1660e01b8152600401611b18919061457f565b6020604051808303816000875af1158015611b37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5b9190613c4b565b5060010161195a565b505060208101515160005b81811015611ea85760007f0000000000000000000000000711b6026068f736bae6b213031fce978d48e02673ffffffffffffffffffffffffffffffffffffffff1663f7888aec85602001518481518110611bcb57611bcb613aba565b6020908102919091010151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152306024820152604401602060405180830381865afa158015611c46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6a9190613c4b565b90506000611c7a6008600a61496a565b85602001518481518110611c9057611c90613aba565b60200260200101516040015167ffffffffffffffff1683611cb19190614979565b611cbb91906149b6565b90507f0000000000000000000000000711b6026068f736bae6b213031fce978d48e02673ffffffffffffffffffffffffffffffffffffffff1663f18d03cc86602001518581518110611d0f57611d0f613aba565b6020026020010151600001513088602001518781518110611d3257611d32613aba565b60209081029190910181015101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff9384166004820152918316602483015291909116604482015260648101849052608401600060405180830381600087803b158015611dbe57600080fd5b505af1158015611dd2573d6000803e3d6000fd5b5050505084602001518381518110611dec57611dec613aba565b60200260200101516020015173ffffffffffffffffffffffffffffffffffffffff1663627dd56a86602001518581518110611e2957611e29613aba565b6020026020010151606001516040518263ffffffff1660e01b8152600401611e51919061457f565b6020604051808303816000875af1158015611e70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e949190613c4b565b505050611ea18160010190565b9050611b6f565b505060408101515160005b818110156112355760007f0000000000000000000000000711b6026068f736bae6b213031fce978d48e02673ffffffffffffffffffffffffffffffffffffffff1663f7888aec85604001518481518110611f0f57611f0f613aba565b6020908102919091010151516040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152306024820152604401602060405180830381865afa158015611f8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fae9190613c4b565b905083604001518281518110611fc657611fc6613aba565b60200260200101516060015181101561200b576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8360400151828151811061202157612021613aba565b60200260200101516040015115612169577f0000000000000000000000000711b6026068f736bae6b213031fce978d48e02673ffffffffffffffffffffffffffffffffffffffff166397da6d308560400151848151811061208457612084613aba565b60200260200101516000015130876040015186815181106120a7576120a7613aba565b60209081029190910181015101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff93841660048201529183166024830152919091166044820152600060648201526084810184905260a40160408051808303816000875af115801561213e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121629190614613565b5050612283565b7f0000000000000000000000000711b6026068f736bae6b213031fce978d48e02673ffffffffffffffffffffffffffffffffffffffff1663f18d03cc856040015184815181106121bb576121bb613aba565b60200260200101516000015130876040015186815181106121de576121de613aba565b60209081029190910181015101516040517fffffffff0000000000000000000000000000000000000000000000000000000060e086901b16815273ffffffffffffffffffffffffffffffffffffffff9384166004820152918316602483015291909116604482015260648101849052608401600060405180830381600087803b15801561226a57600080fd5b505af115801561227e573d6000803e3d6000fd5b505050505b50600101611eb3565b60008461010001518484848861014001516040516020016122b19594939291906149f1565b60405160208183030381529060405290507f00000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd73ffffffffffffffffffffffffffffffffffffffff16639fbf10fc47876000015188604001518960600151338b60800151600014156123b55760208c01516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561238c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123b09190613c4b565b6123bb565b8b608001515b8c60a0015160405180606001604052808f610120015181526020018f60c0015181526020018f60e00151604051602001612420919060609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b6040516020818303038152906040528152508e60e00151604051602001612472919060609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b6040516020818303038152906040528b6040518b63ffffffff1660e01b81526004016124a699989796959493929190614a59565b6000604051808303818588803b1580156124bf57600080fd5b505af11580156124d3573d6000803e3d6000fd5b50506040517fa87376e90000000000000000000000000000000000000000000000000000000081527e0100000000000000000000000000000000000000000000000000000000000060048201527f0000000000000000000000000cff9acef65a64b5d76e83b70787b27f7416644c73ffffffffffffffffffffffffffffffffffffffff16935063a87376e992506024019050600060405180830381600087803b15801561257f57600080fd5b505af1158015612593573d6000803e3d6000fd5b505050506101408501516040517fef89f27cad105cfe7c63f4a5c70e6b1392b571ff544a83de4bf71ceb46bacfee90600090a25050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112359084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612d7f565b80158061274157506040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015284169063dd62ed3e90604401602060405180830381865afa15801561271b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273f9190613c4b565b155b6127cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401611496565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112359084907f095ea7b3000000000000000000000000000000000000000000000000000000009060640161261f565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526112ba9085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161261f565b60606002835110156128ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f556e697377617056324c6962726172793a20494e56414c49445f5041544800006044820152606401611496565b825167ffffffffffffffff81111561290957612909613585565b604051908082528060200260200182016040528015612932578160200160208202803683370190505b509050838160008151811061294957612949613aba565b60200260200101818152505060005b60018451612966919061470c565b811015612a1f576000806129ba8887858151811061298657612986613aba565b60200260200101518886600161299c9190614ae4565b815181106129ac576129ac613aba565b602002602001015188612e8b565b915091506129e28484815181106129d3576129d3613aba565b60200260200101518383612f8c565b846129ee856001614ae4565b815181106129fe576129fe613aba565b60200260200101818152505050508080612a1790614afc565b915050612958565b50949350505050565b6000806000612a378686613106565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084811b8216602084015283901b166034820152919350915087906048016040516020818303038152906040528051906020012085604051602001612b01939291907fff00000000000000000000000000000000000000000000000000000000000000815260609390931b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830191909152603582015260550190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190528051602090910120979650505050505050565b60005b60018351612b53919061470c565b8110156112ba57600080848381518110612b6f57612b6f613aba565b602002602001015185846001612b859190614ae4565b81518110612b9557612b95613aba565b6020026020010151915091506000612bad8383613106565b509050600087612bbe866001614ae4565b81518110612bce57612bce613aba565b602002602001015190506000808373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614612c1657826000612c1a565b6000835b91509150600060028a51612c2e919061470c565b8810612c3a5788612c7b565b612c7b7f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4878c612c6b8c6002614ae4565b815181106114fa576114fa613aba565b9050612cc97f000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c488887fe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303612a28565b73ffffffffffffffffffffffffffffffffffffffff1663022c0d9f84848460006040519080825280601f01601f191660200182016040528015612d13576020820181803683370190505b506040518563ffffffff1660e01b8152600401612d339493929190614b35565b600060405180830381600087803b158015612d4d57600080fd5b505af1158015612d61573d6000803e3d6000fd5b50505050505050505050508080612d7790614afc565b915050612b45565b6000612de1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661328b9092919063ffffffff16565b8051909150156112355780806020019051810190612dff9190614b70565b611235576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611496565b6000806000612e9a8686613106565b509050600080612eac89898989612a28565b73ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015612ef6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f1a9190614ba9565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691508273ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614612f79578082612f7c565b81815b909a909950975050505050505050565b600080841161301d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4960448201527f4e5055545f414d4f554e540000000000000000000000000000000000000000006064820152608401611496565b60008311801561302d5750600082115b6130b9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4c60448201527f49515549444954590000000000000000000000000000000000000000000000006064820152608401611496565b60006130c7856103e56132a4565b905060006130d582856132a4565b905060006130ef836130e9886103e86132a4565b90613334565b90506130fb81836149b6565b979650505050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614156131c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f556e697377617056324c6962726172793a204944454e544943414c5f4144445260448201527f45535345530000000000000000000000000000000000000000000000000000006064820152608401611496565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16106131ff578284613202565b83835b909250905073ffffffffffffffffffffffffffffffffffffffff8216613284576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f556e697377617056324c6962726172793a205a45524f5f4144445245535300006044820152606401611496565b9250929050565b606061329a84846000856133ac565b90505b9392505050565b60008115806132c8575082826132ba8183614979565b92506132c690836149b6565b145b61332e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f770000000000000000000000006044820152606401611496565b92915050565b6000826133418382614ae4565b915081101561332e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f770000000000000000000000006044820152606401611496565b60608247101561343e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401611496565b73ffffffffffffffffffffffffffffffffffffffff85163b6134bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611496565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516134e59190614bf9565b60006040518083038185875af1925050503d8060008114613522576040519150601f19603f3d011682016040523d82523d6000602084013e613527565b606091505b50915091506130fb8282866060831561354157508161329d565b8251156135515782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611496919061457f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff811182821017156135d7576135d7613585565b60405290565b6040805190810167ffffffffffffffff811182821017156135d7576135d7613585565b6040516060810167ffffffffffffffff811182821017156135d7576135d7613585565b60405160a0810167ffffffffffffffff811182821017156135d7576135d7613585565b604051610160810167ffffffffffffffff811182821017156135d7576135d7613585565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156136b1576136b1613585565b604052919050565b600067ffffffffffffffff8211156136d3576136d3613585565b5060051b60200190565b60ff81168114610ed157600080fd5b600082601f8301126136fd57600080fd5b8135602061371261370d836136b9565b61366a565b82815260059290921b8401810191818101908684111561373157600080fd5b8286015b8481101561374c5780358352918301918301613735565b509695505050505050565b600067ffffffffffffffff82111561377157613771613585565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f8301126137ae57600080fd5b81356137bc61370d82613757565b8181528460208386010111156137d157600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f8301126137ff57600080fd5b8135602061380f61370d836136b9565b82815260059290921b8401810191818101908684111561382e57600080fd5b8286015b8481101561374c57803567ffffffffffffffff8111156138525760008081fd5b6138608986838b010161379d565b845250918301918301613832565b60008060006060848603121561388357600080fd5b833567ffffffffffffffff8082111561389b57600080fd5b818601915086601f8301126138af57600080fd5b813560206138bf61370d836136b9565b82815260059290921b8401810191818101908a8411156138de57600080fd5b948201945b838610156139055785356138f6816136dd565b825294820194908201906138e3565b9750508701359250508082111561391b57600080fd5b613927878388016136ec565b9350604086013591508082111561393d57600080fd5b5061394a868287016137ee565b9150509250925092565b61ffff81168114610ed157600080fd5b73ffffffffffffffffffffffffffffffffffffffff81168114610ed157600080fd5b60008060008060008060c0878903121561399f57600080fd5b86356139aa81613954565b955060208701356139ba816136dd565b945060408701356139ca81613964565b9350606087013592506080870135915060a087013567ffffffffffffffff8111156139f457600080fd5b613a0089828a0161379d565b9150509295509295509295565b60008060008060008060c08789031215613a2657600080fd5b8635613a3181613954565b9550602087013567ffffffffffffffff80821115613a4e57600080fd5b613a5a8a838b0161379d565b96506040890135955060608901359150613a7382613964565b9093506080880135925060a08801359080821115613a9057600080fd5b50613a0089828a0161379d565b600060208284031215613aaf57600080fd5b813561329d81613964565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8051613af481613964565b919050565b80518015158114613af457600080fd5b600080600080600060a08688031215613b2157600080fd5b8551613b2c81613964565b9450613b3a60208701613af9565b93506040860151613b4a816136dd565b6060870151608090970151959894975095949392505050565b60008060008060808587031215613b7957600080fd5b8451613b8481613964565b6020860151909450613b9581613964565b6040860151606090960151949790965092505050565b600080600080600060a08688031215613bc357600080fd5b8551613bce81613964565b6020870151909550613bdf81613964565b6040870151606088015191955093509150613bfc60808701613af9565b90509295509295909350565b600080600060608486031215613c1d57600080fd5b8351613c2881613964565b6020850151909350613c3981613964565b80925050604084015190509250925092565b600060208284031215613c5d57600080fd5b5051919050565b60008060408385031215613c7757600080fd5b8251613c8281613964565b6020840151909250613c9381613964565b809150509250929050565b60008060008060808587031215613cb457600080fd5b845193506020808601519350604086015167ffffffffffffffff811115613cda57600080fd5b8601601f81018813613ceb57600080fd5b8051613cf961370d826136b9565b81815260059190911b8201830190838101908a831115613d1857600080fd5b928401925b82841015613d3f578351613d3081613964565b82529284019290840190613d1d565b8096505050505050613d5360608601613ae9565b905092959194509250565b60005b83811015613d79578181015183820152602001613d61565b838111156112ba5750506000910152565b600082601f830112613d9b57600080fd5b8151613da961370d82613757565b818152846020838601011115613dbe57600080fd5b613dcf826020830160208701613d5e565b949350505050565b60006020808385031215613dea57600080fd5b825167ffffffffffffffff80821115613e0257600080fd5b9084019060808287031215613e1657600080fd5b613e1e6135b4565b8251613e2981613964565b8152828401518482015260408084015181830152606084015183811115613e4f57600080fd5b80850194505087601f850112613e6457600080fd5b8351613e7261370d826136b9565b81815260059190911b8501860190868101908a831115613e9157600080fd5b8787015b83811015613f2b57805187811115613ead5760008081fd5b8801808d037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001861315613ee15760008081fd5b613ee96135dd565b8a820151613ef681613964565b81528187015189811115613f0a5760008081fd5b613f188f8d83860101613d8a565b828d015250845250918801918801613e95565b506060850152509198975050505050505050565b600082601f830112613f5057600080fd5b81516020613f6061370d836136b9565b82815260059290921b84018101918181019086841115613f7f57600080fd5b8286015b8481101561374c57805167ffffffffffffffff80821115613fa45760008081fd5b81890191506080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215613fdd5760008081fd5b613fe56135b4565b87840151613ff281613964565b815260408481015161400381613964565b828a0152606085810151858116811461401c5760008081fd5b8383015292850151928484111561403557600091508182fd5b6140438e8b86890101613d8a565b90830152508652505050918301918301613f83565b600082601f83011261406957600080fd5b8151602061407961370d836136b9565b82815260079290921b8401810191818101908684111561409857600080fd5b8286015b8481101561374c57608081890312156140b55760008081fd5b6140bd6135b4565b81516140c881613964565b8152818501516140d781613964565b8186015260406140e8838201613af9565b908201526060828101519082015283529183019160800161409c565b6000602080838503121561411757600080fd5b825167ffffffffffffffff8082111561412f57600080fd5b908401906060828703121561414357600080fd5b61414b613600565b82518281111561415a57600080fd5b8301601f8101881361416b57600080fd5b805161417961370d826136b9565b81815260059190911b8201860190868101908a83111561419857600080fd5b8784015b83811015614260578051878111156141b357600080fd5b850160a0818e037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00112156141e757600080fd5b6141ef613623565b8a8201516141fc81613964565b8152604082015161420c81613964565b818c015261421c60608301613af9565b60408201526080820151606082015260a08201518981111561423e5760008081fd5b61424c8f8d83860101613d8a565b60808301525084525091880191880161419c565b508452505050828401518281111561427757600080fd5b61428388828601613f3f565b8583015250604083015193508184111561429c57600080fd5b6142a887858501614058565b60408201529695505050505050565b8051613af481613954565b600082601f8301126142d357600080fd5b815160206142e361370d836136b9565b82815260059290921b8401810191818101908684111561430257600080fd5b8286015b8481101561374c578051614319816136dd565b8352918301918301614306565b600082601f83011261433757600080fd5b8151602061434761370d836136b9565b82815260059290921b8401810191818101908684111561436657600080fd5b8286015b8481101561374c578051835291830191830161436a565b600082601f83011261439257600080fd5b815160206143a261370d836136b9565b82815260059290921b840181019181810190868411156143c157600080fd5b8286015b8481101561374c57805167ffffffffffffffff8111156143e55760008081fd5b6143f38986838b0101613d8a565b8452509183019183016143c5565b6000806000808486036101c081121561441957600080fd5b6101608082121561442957600080fd5b614431613646565b915061443c876142b7565b825261444a60208801613ae9565b602083015260408701516040830152606087015160608301526080870151608083015260a087015160a083015260c087015160c083015261448d60e08801613ae9565b60e08301526101006144a0818901613ae9565b908301526101208781015190830152610140808801519083015286015190945067ffffffffffffffff808211156144d657600080fd5b6144e2888389016142c2565b94506101808701519150808211156144f957600080fd5b61450588838901614326565b93506101a087015191508082111561451c57600080fd5b5061452987828801614381565b91505092959194509250565b6000815180845261454d816020860160208601613d5e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061329d6020830184614535565b80518252602081015160208301526000604082015160606040850152613dcf6060850182614535565b61ffff8616815260ff8516602082015260a0604082015260006145e160a0830186614535565b82810360608401526145f38186614535565b905082810360808401526146078185614592565b98975050505050505050565b6000806040838503121561462657600080fd5b505080516020909101519092909150565b600080600080600060a0868803121561464f57600080fd5b855161465a81613964565b602087015190955067ffffffffffffffff8082111561467857600080fd5b61468489838a016142c2565b9550604088015191508082111561469a57600080fd5b6146a689838a01614326565b945060608801519150808211156146bc57600080fd5b506146c988828901614381565b925050608086015190509295509295909350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561471e5761471e6146dd565b500390565b600081518084526020808501945080840160005b8381101561475657815160ff1687529582019590820190600101614737565b509495945050505050565b600081518084526020808501945080840160005b8381101561475657815187529582019590820190600101614775565b600082825180855260208086019550808260051b84010181860160005b848110156147fa577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08684030189526147e8838351614535565b988401989250908301906001016147ae565b5090979650505050505050565b60608152600061481a6060830186614723565b828103602084015261482c8186614761565b905082810360408401526148408185614791565b9695505050505050565b600181815b808511156148a357817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115614889576148896146dd565b8085161561489657918102915b93841c939080029061484f565b509250929050565b6000826148ba5750600161332e565b816148c75750600061332e565b81600181146148dd57600281146148e757614903565b600191505061332e565b60ff8411156148f8576148f86146dd565b50506001821b61332e565b5060208310610133831016604e8410600b8410161715614926575081810a61332e565b614930838361484a565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115614962576149626146dd565b029392505050565b600061329d60ff8416836148ab565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156149b1576149b16146dd565b500290565b6000826149ec577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b73ffffffffffffffffffffffffffffffffffffffff8616815260a060208201526000614a2060a0830187614723565b8281036040840152614a328187614761565b90508281036060840152614a468186614791565b9150508260808301529695505050505050565b600061012061ffff8c1683528a602084015289604084015273ffffffffffffffffffffffffffffffffffffffff891660608401528760808401528660a08401528060c0840152614aab81840187614592565b905082810360e0840152614abf8186614535565b9050828103610100840152614ad48185614535565b9c9b505050505050505050505050565b60008219821115614af757614af76146dd565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415614b2e57614b2e6146dd565b5060010190565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006148406080830184614535565b600060208284031215614b8257600080fd5b61329d82613af9565b80516dffffffffffffffffffffffffffff81168114613af457600080fd5b600080600060608486031215614bbe57600080fd5b614bc784614b8b565b9250614bd560208501614b8b565b9150604084015163ffffffff81168114614bee57600080fd5b809150509250925092565b60008251614c0b818460208701613d5e565b919091019291505056fea26469706673582212200eb89d099dfbd48538588aed7bd5e9992174fa244f34fb820dbfbac72d39d98d64736f6c634300080b0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000000711b6026068f736bae6b213031fce978d48e02600000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4e18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c63030000000000000000000000000cff9acef65a64b5d76e83b70787b27f7416644c

-----Decoded View---------------
Arg [0] : _bentoBox (address): 0x0711B6026068f736bae6B213031fCE978D48E026
Arg [1] : _stargateRouter (address): 0x45A01E4e04F14f7A4a6702c74187c5F6222033cd
Arg [2] : _factory (address): 0xc35DADB65012eC5796536bD9864eD8773aBc74C4
Arg [3] : _pairCodeHash (bytes32): 0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303
Arg [4] : _stargateWidget (address): 0x0cFF9ACef65A64B5D76e83B70787b27F7416644C

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000000711b6026068f736bae6b213031fce978d48e026
Arg [1] : 00000000000000000000000045a01e4e04f14f7a4a6702c74187c5f6222033cd
Arg [2] : 000000000000000000000000c35dadb65012ec5796536bd9864ed8773abc74c4
Arg [3] : e18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303
Arg [4] : 0000000000000000000000000cff9acef65a64b5d76e83b70787b27f7416644c


Block Transaction Gas Used Reward
view all blocks ##produced##

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.