ETH Price: $3,367.92 (-3.40%)

Contract

0xd2E730431e67C0ea24161D0ACeF9389fd744C862
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Swap V2Exact In214523802024-12-21 17:28:474 days ago1734802127IN
0xd2E73043...fd744C862
0 ETH0.001170497.32327827
Swap V2Exact In214519252024-12-21 15:57:234 days ago1734796643IN
0xd2E73043...fd744C862
0.03 ETH0.001569558.88918811
Swap V2Exact In214518542024-12-21 15:43:114 days ago1734795791IN
0xd2E73043...fd744C862
0 ETH0.001739079.28260179
Swap V2Exact In214517512024-12-21 15:22:354 days ago1734794555IN
0xd2E73043...fd744C862
0.04 ETH0.001644069.31116019
Swap V2Exact In214506872024-12-21 11:48:474 days ago1734781727IN
0xd2E73043...fd744C862
0 ETH0.001316327.80994386
Swap V2Exact In214506282024-12-21 11:36:594 days ago1734781019IN
0xd2E73043...fd744C862
0 ETH0.00158159.38263406
Swap V2Exact In214504752024-12-21 11:06:114 days ago1734779171IN
0xd2E73043...fd744C862
0 ETH0.001632157.75416276
Swap V2Exact In214501532024-12-21 10:01:474 days ago1734775307IN
0xd2E73043...fd744C862
0.02 ETH0.001571818.72288317
Swap V2Exact In214501462024-12-21 10:00:234 days ago1734775223IN
0xd2E73043...fd744C862
0.03 ETH0.001559858.34693285
Swap V2Exact In214492112024-12-21 6:52:115 days ago1734763931IN
0xd2E73043...fd744C862
0 ETH0.0022284510.26130614
Swap V2Exact In214487512024-12-21 5:19:355 days ago1734758375IN
0xd2E73043...fd744C862
0.03 ETH0.001349656.6412603
Swap V2Exact In214350992024-12-19 7:32:597 days ago1734593579IN
0xd2E73043...fd744C862
0.05 ETH0.0020613211.1198419
Swap V2Exact In214265942024-12-18 3:00:478 days ago1734490847IN
0xd2E73043...fd744C862
0 ETH0.0028051412.32688483
Swap V2Exact In214261932024-12-18 1:39:598 days ago1734485999IN
0xd2E73043...fd744C862
0.03 ETH0.001375858.19926666
Swap V2Exact In214261872024-12-18 1:38:478 days ago1734485927IN
0xd2E73043...fd744C862
0 ETH0.001761759.84432984
Swap V2Exact In214260512024-12-18 1:10:598 days ago1734484259IN
0xd2E73043...fd744C862
0.04 ETH0.0021519711.60882188
Swap V2Exact In214260182024-12-18 1:04:238 days ago1734483863IN
0xd2E73043...fd744C862
0.03 ETH0.0022340511.4380183
Swap V2Exact In214260012024-12-18 1:00:598 days ago1734483659IN
0xd2E73043...fd744C862
0.03 ETH0.002176849.77327264
Swap V2Exact In214226982024-12-17 13:56:598 days ago1734443819IN
0xd2E73043...fd744C862
0.035 ETH0.0040465121.82749153
Swap V2Exact In214226872024-12-17 13:54:478 days ago1734443687IN
0xd2E73043...fd744C862
0 ETH0.0041652922.23148352
Swap V2Exact In214216602024-12-17 10:28:478 days ago1734431327IN
0xd2E73043...fd744C862
0 ETH0.0020880910.74255389
Swap V2Exact In214215702024-12-17 10:10:478 days ago1734430247IN
0xd2E73043...fd744C862
0.04 ETH0.0018402711.07497925
Swap V2Exact In214215672024-12-17 10:10:118 days ago1734430211IN
0xd2E73043...fd744C862
0.04 ETH0.0020709410.80974145
Swap V2Exact In214215622024-12-17 10:09:118 days ago1734430151IN
0xd2E73043...fd744C862
0 ETH0.002195811.19960427
Swap V2Exact In214213902024-12-17 9:34:358 days ago1734428075IN
0xd2E73043...fd744C862
0.01 ETH0.001637569.59066607
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
214523802024-12-21 17:28:474 days ago1734802127
0xd2E73043...fd744C862
0.04705425 ETH
214523802024-12-21 17:28:474 days ago1734802127
0xd2E73043...fd744C862
0.04705425 ETH
214519252024-12-21 15:57:234 days ago1734796643
0xd2E73043...fd744C862
0.0297 ETH
214519252024-12-21 15:57:234 days ago1734796643
0xd2E73043...fd744C862
0.0003 ETH
214518542024-12-21 15:43:114 days ago1734795791
0xd2E73043...fd744C862
0.06330757 ETH
214518542024-12-21 15:43:114 days ago1734795791
0xd2E73043...fd744C862
0.06330757 ETH
214517512024-12-21 15:22:354 days ago1734794555
0xd2E73043...fd744C862
0.0396 ETH
214517512024-12-21 15:22:354 days ago1734794555
0xd2E73043...fd744C862
0.0004 ETH
214506872024-12-21 11:48:474 days ago1734781727
0xd2E73043...fd744C862
0.05021183 ETH
214506872024-12-21 11:48:474 days ago1734781727
0xd2E73043...fd744C862
0.05021183 ETH
214506282024-12-21 11:36:594 days ago1734781019
0xd2E73043...fd744C862
0.09461573 ETH
214506282024-12-21 11:36:594 days ago1734781019
0xd2E73043...fd744C862
0.09461573 ETH
214504752024-12-21 11:06:114 days ago1734779171
0xd2E73043...fd744C862
0.06843212 ETH
214504752024-12-21 11:06:114 days ago1734779171
0xd2E73043...fd744C862
0.06843212 ETH
214501532024-12-21 10:01:474 days ago1734775307
0xd2E73043...fd744C862
0.0198 ETH
214501532024-12-21 10:01:474 days ago1734775307
0xd2E73043...fd744C862
0.0002 ETH
214501462024-12-21 10:00:234 days ago1734775223
0xd2E73043...fd744C862
0.0297 ETH
214501462024-12-21 10:00:234 days ago1734775223
0xd2E73043...fd744C862
0.0003 ETH
214492112024-12-21 6:52:115 days ago1734763931
0xd2E73043...fd744C862
0.06214911 ETH
214492112024-12-21 6:52:115 days ago1734763931
0xd2E73043...fd744C862
0.06214911 ETH
214487512024-12-21 5:19:355 days ago1734758375
0xd2E73043...fd744C862
0.0297 ETH
214487512024-12-21 5:19:355 days ago1734758375
0xd2E73043...fd744C862
0.0003 ETH
214350992024-12-19 7:32:597 days ago1734593579
0xd2E73043...fd744C862
0.0495 ETH
214350992024-12-19 7:32:597 days ago1734593579
0xd2E73043...fd744C862
0.0005 ETH
214265942024-12-18 3:00:478 days ago1734490847
0xd2E73043...fd744C862
0.00978963 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SwapX

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license
File 1 of 22 : SwapX.sol
// SPDX-License-Identifier: MIT

pragma solidity >= 0.8.0;

import "./contracts-upgradeable/security/PausableUpgradeable.sol";
import "./contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "./contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "./contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import "./contracts-upgradeable/access/OwnableUpgradeable.sol";
import "./contracts-upgradeable/proxy/utils/Initializable.sol";
import "./utils/SafeMath.sol";
import "./libs/Path.sol";
import "./libs/TickMath.sol";
import "./libs/SafeCast.sol";
import "./libs/UniswapV2Library.sol";
import "./libs/CallbackValidation.sol";
import "./interfaces/IUniswapV2Pair.sol";
import "./interfaces/IUniswapV3Pool.sol";
import "./interfaces/IUniswapV3SwapCallback.sol";
import "./Storage.sol";

interface IWETH is IERC20Upgradeable {
    /// @notice Deposit ether to get wrapped ether
    function deposit() external payable;

    /// @notice Withdraw wrapped ether to get ether
    function withdraw(uint256) external;
}

contract SwapX is Storage, IUniswapV3SwapCallback, Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable {

    using SafeERC20Upgradeable for IERC20Upgradeable;
    using SafeMath for uint;
    using Path for bytes;
    using SafeCast for uint256;

    struct ExactInputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 deadline;
        uint256 amountIn;
        uint256 amountOutMinimum;
        uint160 sqrtPriceLimitX96;
    }

    struct ExactInputParams {
        bytes path;
        address recipient;
        uint256 deadline;
        uint256 amountIn;
        uint256 amountOutMinimum;
    }


    struct ExactOutputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 deadline;
        uint256 amountOut;
        uint256 amountInMaximum;
        uint160 sqrtPriceLimitX96;
    }

    struct ExactOutputParams {
        bytes path;
        address tokenIn;
        address recipient;
        uint256 deadline;
        uint256 amountOut;
        uint256 amountInMaximum;
    }

    struct ExactInputMixedParams {
        string[] routes;
        bytes path1;
        address factory1;
        bytes path2;
        address factory2;
        address recipient;
        uint256 deadline;
        uint256 amountIn;
        uint256 amountOutMinimum;
    }

    struct ExactOutputMixedParams {
        string[] routes;
        bytes path1;
        address factory1;
        bytes path2;
        address factory2;
        uint256 amountIn2; // only for v2-v3 router
        address recipient;
        uint256 deadline;
        uint256 amountOut;
        uint256 amountInMaximum;
    }

    struct SwapCallbackData {
        bytes path;
        address payer;
    }

    event FeeCollected(address indexed token, address indexed payer, uint256 amount, uint256 timestamp);

    modifier checkDeadline(uint256 deadline) {
        require(block.timestamp <= deadline, 'Transaction too old');
        _;
    }

    receive() external payable {}

    function initialize (
        address _factoryV2,
        address _factoryV3,
        address _WETH,
        address _feeCollector,
        uint256 _feeRate
    ) public initializer {
        __Ownable_init(msg.sender);
        __ReentrancyGuard_init();
        __Pausable_init();

        factoryV2 = _factoryV2;
        factoryV3 = _factoryV3;
        feeCollector = _feeCollector;
        feeRate = _feeRate;
        feeDenominator = 10000;
        WETH = _WETH;
        amountInCached = type(uint256).max;
    }

    // take fee
    function takeFee(address tokenIn, uint256 amountIn) internal returns (uint256){
        if (feeExcludeList[msg.sender])
            return 0;

        uint256 fee = amountIn.mul(feeRate).div(feeDenominator);

        if (( tokenIn == address(0) || tokenIn == WETH ) && address(this).balance > fee ) {
            (bool success, ) = address(feeCollector).call{ value: fee }("");
            require(success, "SwapX: take fee error");
        } else
            IERC20Upgradeable(tokenIn).safeTransferFrom(msg.sender, feeCollector, fee);
        
        emit FeeCollected(tokenIn, msg.sender, fee, block.timestamp);

        return fee; 
    }

    // V2: Any swap, ExactIn single-hop - SupportingFeeOnTransferTokens
    function swapV2ExactIn(
        address tokenIn, 
        address tokenOut, 
        uint256 amountIn, 
        uint256 amountOutMin, 
        address poolAddress
    ) payable public nonReentrant whenNotPaused returns (uint amountOut){

        require(poolAddress != address(0), "SwapX: invalid pool address");
        require(amountIn > 0, "SwapX: amout in is zero");

        bool nativeIn = false;
        if (tokenIn == address(0)) {
            require(msg.value >= amountIn, "SwapX: amount in and value mismatch");
            nativeIn = true;
            tokenIn = WETH;
            // refund
            uint amount = msg.value - amountIn;
            if (amount > 0) {
              (bool success, ) = address(msg.sender).call{value: amount}("");
              require(success, "SwapX: refund ETH error");
            }
        }
        uint256 fee = takeFee(tokenIn, amountIn);
        amountIn = amountIn - fee;

        if (nativeIn) {
            pay(tokenIn, address(this), poolAddress, amountIn);
        } else
            pay(tokenIn, msg.sender, poolAddress, amountIn);

        bool nativeOut = false;
        if (tokenOut == address(0))
            nativeOut = true;

        uint balanceBefore = nativeOut ? 
            IERC20Upgradeable(WETH).balanceOf(address(this)) :  IERC20Upgradeable(tokenOut).balanceOf(msg.sender);
        
        IUniswapV2Pair pair = IUniswapV2Pair(poolAddress);
        address token0 = pair.token0();
        uint amountInput;
        uint amountOutput;
        { // scope to avoid stack too deep errors
            (uint reserve0, uint reserve1,) = pair.getReserves();
            (uint reserveInput, uint reserveOutput) = tokenIn == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
            amountInput = IERC20Upgradeable(tokenIn).balanceOf(address(pair)).sub(reserveInput);
            amountOutput = UniswapV2Library.getAmountOut(amountInput, reserveInput, reserveOutput);
        }
        (uint amount0Out, uint amount1Out) = tokenIn == token0 ? (uint(0), amountOutput) : (amountOutput, uint(0));
        address to = nativeOut ? address(this) : msg.sender;
        pair.swap(amount0Out, amount1Out, to, new bytes(0));

        if (nativeOut) {
            amountOut = IERC20Upgradeable(WETH).balanceOf(address(this)).sub(balanceBefore);
            IWETH(WETH).withdraw(amountOut);
            (bool success, ) = address(msg.sender).call{value: amountOut}("");
            require(success, "SwapX: send ETH out error");
        } else {
            amountOut = IERC20Upgradeable(tokenOut).balanceOf(msg.sender).sub(balanceBefore);
        }
        require(
            amountOut >= amountOutMin,
            'SwapX: insufficient output amount'
        );
    }

    // V2: Any swap, ExactOut single-hop - * not support fee-on-transfer tokens *
    function swapV2ExactOut(
        address tokenIn, 
        address tokenOut, 
        uint256 amountInMax, 
        uint256 amountOut, 
        address poolAddress
     ) payable public nonReentrant whenNotPaused returns (uint amountIn){

        require(poolAddress != address(0), "SwapX: invalid pool address");
        require(amountInMax > 0, "SwapX: amout in max is zero");

        bool nativeIn = false;
        if (tokenIn == address(0)) {
            tokenIn = WETH;
            nativeIn = true;
            require(msg.value >= amountInMax, "SwapX: amount in and value mismatch");
        }

        bool nativeOut = false;
        if (tokenOut == address(0)) {
            nativeOut = true;
        }

        IUniswapV2Pair pair = IUniswapV2Pair(poolAddress);
        address token0 = pair.token0();
        { // scope to avoid stack too deep errors
            (uint reserve0, uint reserve1,) = pair.getReserves();
            (uint reserveInput, uint reserveOutput) = tokenIn == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
            amountIn = UniswapV2Library.getAmountIn(amountOut, reserveInput, reserveOutput);

            uint256 fee = takeFee(tokenIn, amountIn);

            require(amountIn + fee <= amountInMax, "SwapX: excessive input amount");
            if(nativeIn) {
                pay(tokenIn, address(this), poolAddress, amountIn);
                uint amount = msg.value - amountIn - fee;
                // refund
                if (amount > 0) {
                    (bool success, ) = address(msg.sender).call{value: amount}("");
                    require(success, "SwapX: refund ETH error");
                }
            } else { 
                pay(tokenIn, msg.sender, poolAddress, amountIn);
            }
        }
        (uint amount0Out, uint amount1Out) = tokenIn == token0 ? (uint(0), amountOut) : (amountOut, uint(0));
        address to = nativeOut ? address(this) : msg.sender;
        pair.swap(amount0Out, amount1Out, to, new bytes(0));

        if (nativeOut) {
            IWETH(WETH).withdraw(amountOut);
            (bool success, ) = address(msg.sender).call{value: amountOut}("");
            require(success, "SwapX: send ETH out error");
        }
    }

     // **** SWAP ****
    // requires the initial amount to have already been sent to the first pair
    function _swap(uint[] memory amounts, address[] memory path, address _to, address _factory) internal virtual {
        for (uint i; i < path.length - 1; i++) {
            (address input, address output) = (path[i], path[i + 1]);
            (address token0,) = UniswapV2Library.sortTokens(input, output);
            uint amountOut = amounts[i + 1];
            (uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOut) : (amountOut, uint(0));
            address to = i < path.length - 2 ? UniswapV2Library.pairFor(_factory, output, path[i + 2]) : _to;
            IUniswapV2Pair(UniswapV2Library.pairFor(_factory, input, output)).swap(
                amount0Out, amount1Out, to, new bytes(0)
            );
        }
    }

    // **** SWAP (supporting fee-on-transfer tokens) ****
    // requires the initial amount to have already been sent to the first pair
    function _swapSupportingFeeOnTransferTokens(address[] memory path, address _to, address _factory) internal virtual {
        for (uint i; i < path.length - 1; i++) {
            (address input, address output) = (path[i], path[i + 1]);
            (address token0,) = UniswapV2Library.sortTokens(input, output);
            IUniswapV2Pair pair = IUniswapV2Pair(UniswapV2Library.pairFor(_factory, input, output));
            uint amountInput;
            uint amountOutput;
            { // scope to avoid stack too deep errors
                (uint reserve0, uint reserve1,) = pair.getReserves();
                (uint reserveInput, uint reserveOutput) = input == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
                amountInput = IERC20Upgradeable(input).balanceOf(address(pair)).sub(reserveInput);
                amountOutput = UniswapV2Library.getAmountOut(amountInput, reserveInput, reserveOutput);
            }
            (uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOutput) : (amountOutput, uint(0));
            address to = i < path.length - 2 ? UniswapV2Library.pairFor(_factory, output, path[i + 2]) : _to;
            pair.swap(amount0Out, amount1Out, to, new bytes(0));
        }
    }

    // V2-V2: Uniswap/Sushiswap, SupportingFeeOnTransferTokens and multi-hop
    function swapV2MultiHopExactIn(
        address tokenIn,
        uint256 amountIn, 
        uint256 amountOutMin, 
        address[] calldata path, 
        address recipient,
        uint deadline,
        address factory
    ) payable public nonReentrant whenNotPaused checkDeadline(deadline) returns (uint[] memory amounts){

        require(amountIn > 0, "SwapX: amout in is zero");

        bool nativeIn = false;
        if (tokenIn == address(0)) {
            require(msg.value >= amountIn, "SwapX: amount in and value mismatch");
            nativeIn = true;
            tokenIn = WETH;
            // refund
            uint amount = msg.value - amountIn;
            if (amount > 0) {
              (bool success, ) = address(msg.sender).call{value: amount}("");
              require(success, "SwapX: refund ETH error");
            }
        }

        uint256 fee = takeFee(tokenIn, amountIn);
        amountIn = amountIn - fee;

        address firstPool = UniswapV2Library.pairFor(factory, path[0], path[1]);
        if (nativeIn) {
            pay(tokenIn, address(this), firstPool, amountIn);
        } else
            pay(tokenIn, msg.sender, firstPool, amountIn);
        require(tokenIn == path[0], "invalid path");

        amounts = UniswapV2Library.getAmountsOut(factory, amountIn, path);

        uint balanceBefore = IERC20Upgradeable(path[path.length - 1]).balanceOf(recipient);
        _swapSupportingFeeOnTransferTokens(path, recipient, factory);
        uint balanceChanged = IERC20Upgradeable(path[path.length - 1]).balanceOf(recipient).sub(balanceBefore);
        amounts[path.length - 1] = balanceChanged;
        require(
            balanceChanged >= amountOutMin,
            'SwapX: insufficient output amount'
        );
    }

    // V2-V2: Uniswap, ExactOut multi-hop, not support fee-on-transfer token in output
    function swapV2MultiHopExactOut(
        address tokenIn, 
        uint256 amountInMax, 
        uint256 amountOut, 
        address[] calldata path, 
        address recipient,
        uint deadline,
        address factory
    ) payable public nonReentrant whenNotPaused checkDeadline(deadline) returns (uint[] memory amounts){

        require(amountInMax > 0, "SwapX: amount in max is zero");

        bool nativeIn = false;
        if (tokenIn == address(0)) {
            nativeIn = true;
            tokenIn = WETH;
            require(msg.value >= amountInMax, "SwapX: amount in and value mismatch");
        }

        amounts = UniswapV2Library.getAmountsIn(factory, amountOut, path);

        uint256 fee = takeFee(tokenIn, amounts[0]);

        require(amounts[0] + fee <= amountInMax, 'SwapX: excessive input amount');

        address firstPool = UniswapV2Library.pairFor(factory, path[0], path[1]);
        if (nativeIn) {
            pay(tokenIn, address(this), firstPool, amounts[0]);
            uint amount = msg.value - amounts[0] - fee;
            // refund
            if (amount > 0) {
                (bool success, ) = address(msg.sender).call{value: amount}("");
                require(success, "SwapX: refund ETH error");
            }
        } else
            pay(tokenIn, msg.sender, firstPool, amounts[0]);

        _swap(amounts, path, recipient, factory);
    }

    /// UniswapV3SwapCallback
    function uniswapV3SwapCallback(
        int256 amount0Delta,
        int256 amount1Delta,
        bytes calldata _data
    ) external override {
        require(amount0Delta > 0 || amount1Delta > 0); // swaps entirely within 0-liquidity regions are not supported
        SwapCallbackData memory data = abi.decode(_data, (SwapCallbackData));
        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();
        CallbackValidation.verifyCallback(factoryV3, tokenIn, tokenOut, fee);

        (bool isExactInput, uint256 amountToPay) =
            amount0Delta > 0
                ? (tokenIn < tokenOut, uint256(amount0Delta))
                : (tokenOut < tokenIn, uint256(amount1Delta));
        if (isExactInput) {
            pay(tokenIn, data.payer, msg.sender, amountToPay);
        } else {
            // either initiate the next swap or pay
            if (data.path.hasMultiplePools()) {
                data.path = data.path.skipToken();
                exactOutputInternal(amountToPay, msg.sender, 0, data);
            } else {
                amountInCached = amountToPay;
                tokenIn = tokenOut; // swap in/out because exact output swaps are reversed
                pay(tokenIn, data.payer, msg.sender, amountToPay);
            }
        }
    }

    // V3: ExactIn single-hop 
    function swapV3ExactIn (
            ExactInputSingleParams memory params
    ) external payable nonReentrant whenNotPaused checkDeadline(params.deadline) returns (uint256 amountOut) {

        require(params.amountIn > 0, "SwapX: amount in is zero");

        if (params.tokenIn == address(0)) {
            params.tokenIn = WETH;
            require(msg.value >= params.amountIn, "SwapX: amount in and value mismatch");
            // refund
            uint amount = msg.value - params.amountIn;
            if (amount > 0) {
              (bool success, ) = address(msg.sender).call{value: amount}("");
              require(success, "SwapX: refund ETH error");
            }
        }

        uint256 fee = takeFee(params.tokenIn, params.amountIn);
        params.amountIn = params.amountIn - fee;

        bool nativeOut = false;
        if (params.tokenOut == address(0)) {
            params.tokenOut = WETH;
            nativeOut = true;
        }

        amountOut = exactInputInternal(
            params.amountIn,
            nativeOut ? address(0) : params.recipient,
            params.sqrtPriceLimitX96,
            SwapCallbackData({path: abi.encodePacked(params.tokenIn, params.fee, params.tokenOut), payer: msg.sender})
        );

        require(amountOut >= params.amountOutMinimum, "SwapX: insufficient out amount");

        if (nativeOut) {
            IWETH(WETH).withdraw(amountOut);
            (bool success, ) = address(params.recipient).call{value: amountOut}("");
            require(success, "SwapX: send ETH out error");
        }
    }

    // V3: ExactOut single-hop 
    function swapV3ExactOut (
        ExactOutputSingleParams memory params
    ) payable public nonReentrant whenNotPaused checkDeadline(params.deadline) returns (uint256 amountIn) {

        require(params.amountInMaximum > 0, "SwapX: amount in max is zero");

        bool nativeIn = false;
        if (params.tokenIn == address(0)) {
            nativeIn = true;
            params.tokenIn = WETH;
            require(msg.value >= params.amountInMaximum, "SwapX: amount in max and value mismatch");
        }

        bool nativeOut = false;
        if (params.tokenOut == address(0)) {
            params.tokenOut = WETH;
            nativeOut = true;
        }

        amountIn = exactOutputInternal(
            params.amountOut,
            nativeOut ? address(0) : params.recipient,
            params.sqrtPriceLimitX96,
            SwapCallbackData({path: abi.encodePacked(params.tokenOut, params.fee, params.tokenIn), payer: msg.sender})
        );

        uint256 fee = takeFee(params.tokenIn, amountIn);

        require(amountIn + fee <= params.amountInMaximum, "SwapX: too much requested");
        
        if (nativeIn) {
            uint amount = msg.value - amountIn - fee;
            // refund
            if (amount > 0) {
                (bool success, ) = address(msg.sender).call{value: amount}("");
                require(success, "SwapX: refund ETH error");
            }
        } 

        if (nativeOut) {
            IWETH(WETH).withdraw(params.amountOut);
            (bool success, ) = address(params.recipient).call{value: params.amountOut}("");
            require(success, "SwapX: send ETH out error");
        }

        amountInCached = type(uint256).max; 
    }

    // V3-V3: ExactIn multi-hop 
    function swapV3MultiHopExactIn (
        ExactInputParams memory params
    ) payable public nonReentrant whenNotPaused checkDeadline(params.deadline) returns (uint256 amountOut) {

        require(params.amountIn > 0, "SwapX: amount in is zero");
        if (msg.value > 0) {
            require(msg.value >= params.amountIn, "SwapX: amount in and value mismatch");
            // refund
            uint amount = msg.value - params.amountIn;
            if (amount > 0) {
              (bool success, ) = address(msg.sender).call{value: amount}("");
              require(success, "SwapX: refund ETH error");
            }
        }

        (address tokenIn, , ) = params.path.decodeFirstPool();
        uint256 fee = takeFee(tokenIn, params.amountIn);
        params.amountIn = params.amountIn - fee;

        address payer = msg.sender; // msg.sender pays for the first hop

        while (true) {
            bool hasMultiplePools = params.path.hasMultiplePools();

            // the outputs of prior swaps become the inputs to subsequent ones
            params.amountIn = exactInputInternal(
                params.amountIn,
                hasMultiplePools ? address(this) : params.recipient, 
                0,
                SwapCallbackData({
                    path: params.path.getFirstPool(), 
                    payer: payer
                })
            );

            // decide whether to continue or terminate
            if (hasMultiplePools) {
                payer = address(this); // at this point, the caller has paid
                params.path = params.path.skipToken();
            } else {
                amountOut = params.amountIn;
                break;
            }
        }

        require(amountOut >= params.amountOutMinimum, 'SwapX: too little received');
    }

    // V3-V3: ExactOut multi-hop 
    function swapV3MultiHopExactOut(
        ExactOutputParams memory params
    ) external payable nonReentrant whenNotPaused checkDeadline(params.deadline) returns (uint256 amountIn) {

        require(params.amountInMaximum > 0, "SwapX: amount in max is zero");
        if (msg.value > 0)
            require(msg.value >= params.amountInMaximum, "SwapX: amount in max and value mismatch");

        exactOutputInternal(
            params.amountOut,
            params.recipient,
            0,
            SwapCallbackData({path: params.path, payer: msg.sender})
        );

        amountIn = amountInCached;

        uint256 fee = takeFee(params.tokenIn, amountIn);

        require(amountIn + fee <= params.amountInMaximum, 'SwapX: too much requested');

        if (msg.value > 0) {
            // refund
            uint256 amount = msg.value - amountIn - fee;
            if (amount > 0) {
                (bool success, ) = address(msg.sender).call{value: amount}("");
                require(success, "SwapX: refund ETH error");
            }
        }

        amountInCached = type(uint256).max;
    }

    function isStrEqual(string memory str1, string memory str2) internal pure returns(bool) {
        return keccak256(bytes(str1)) == keccak256(bytes(str2));
    }

    // Mixed: ExactIn multi-hop, token not supporting zero address 
    function swapMixedMultiHopExactIn (
        ExactInputMixedParams memory params
    ) payable public nonReentrant whenNotPaused checkDeadline(params.deadline) returns (uint256 amountOut) {

        require(params.routes.length == 2, "SwapX: only 2 routes supported");

        require(params.amountIn > 0, "SwapX: amount in is zero");

        (address tokenIn, address tokenOut1, uint24 fee1) = params.path1.decodeFirstPool();
        bool nativeIn = false;
        if (tokenIn == address(0)) {
            require(msg.value >= params.amountIn, "SwapX: amount in and value mismatch");
            nativeIn = true;
            tokenIn = WETH;
            // refund
            uint amount = msg.value - params.amountIn;
            if (amount > 0) {
              (bool success, ) = address(msg.sender).call{value: amount}("");
              require(success, "SwapX: refund ETH error");
            }
        }
        uint256 fee = takeFee(tokenIn, params.amountIn);
        params.amountIn = params.amountIn - fee;

        if (isStrEqual(params.routes[0], "v2") && isStrEqual(params.routes[1], "v2")) {
            // uni - sushi, or verse
            address poolAddress1 = UniswapV2Library.pairFor(params.factory1, tokenIn, tokenOut1);
            if (nativeIn) {
                pay(tokenIn, address(this), poolAddress1, params.amountIn);
            } else
                pay(tokenIn, msg.sender, poolAddress1, params.amountIn);

            address[] memory path1 = new address[](2);
            path1[0] = tokenIn;
            path1[1] = tokenOut1;

            (, address tokenOut,) = params.path2.decodeFirstPool();
            address[] memory path2 = new address[](2); 
            path2[0] = tokenOut1;
            path2[1] = tokenOut;
            address poolAddress2 = UniswapV2Library.pairFor(params.factory2, tokenOut1, tokenOut);

            uint balanceBefore = IERC20Upgradeable(tokenOut).balanceOf(params.recipient);
            _swapSupportingFeeOnTransferTokens(path1, poolAddress2, params.factory1);
            _swapSupportingFeeOnTransferTokens(path2, params.recipient, params.factory2);
            amountOut = IERC20Upgradeable(tokenOut).balanceOf(params.recipient).sub(balanceBefore);
        } else if (isStrEqual(params.routes[0], "v2") && isStrEqual(params.routes[1], "v3")) {
            address poolAddress1 = UniswapV2Library.pairFor(params.factory1, tokenIn, tokenOut1);
            if (nativeIn) {
                pay(tokenIn, address(this), poolAddress1, params.amountIn);
            } else
                pay(tokenIn, msg.sender, poolAddress1, params.amountIn);

            address[] memory path1 = new address[](2);
            path1[0] = tokenIn;
            path1[1] = tokenOut1;
            uint[] memory amounts1 = UniswapV2Library.getAmountsOut(params.factory1, params.amountIn, path1);
            uint amountOut1 = amounts1[amounts1.length-1];

            (, address tokenOut,) = params.path2.decodeFirstPool();
            uint balanceBefore = IERC20Upgradeable(tokenOut).balanceOf(params.recipient);
            _swapSupportingFeeOnTransferTokens(path1, address(this), params.factory1);

            amountOut = exactInputInternal(
                amountOut1,
                params.recipient, 
                0,
                SwapCallbackData({
                    path: params.path2, 
                    payer: address(this) 
                })
            );
            amountOut = IERC20Upgradeable(tokenOut).balanceOf(params.recipient).sub(balanceBefore);
        } else if (isStrEqual(params.routes[0], "v3") && isStrEqual(params.routes[1], "v2")) {
            (address tokenIn2, address tokenOut,) = params.path2.decodeFirstPool();
            address pairV2Address = UniswapV2Library.pairFor(params.factory2, tokenIn2, tokenOut);

            uint amountOut1 = exactInputInternal(
                params.amountIn,
                pairV2Address, 
                0,
                SwapCallbackData({
                    path: abi.encodePacked(tokenIn, fee1, tokenOut1), 
                    payer: msg.sender 
                })
            );

            address[] memory path2 = new address[](2); 
            path2[0] = tokenIn2;
            path2[1] = tokenOut;
            uint[] memory amounts2 = UniswapV2Library.getAmountsOut(params.factory2, amountOut1, path2);
            amountOut = amounts2[amounts2.length - 1];

            uint balanceBefore = IERC20Upgradeable(tokenOut).balanceOf(params.recipient);
            _swapSupportingFeeOnTransferTokens(path2, params.recipient, params.factory2);
            amountOut = IERC20Upgradeable(tokenOut).balanceOf(params.recipient).sub(balanceBefore);
        } else if (isStrEqual(params.routes[0], "v3") && isStrEqual(params.routes[1], "v3")) {
            // uni - uni, same as swapMultiHopExactIn
            params.amountIn = exactInputInternal(
                params.amountIn,
                address(this), 
                0,
                SwapCallbackData({
                    path: abi.encodePacked(tokenIn, fee1, tokenOut1), 
                    payer: msg.sender 
                })
            );

            amountOut = exactInputInternal(
                params.amountIn,
                params.recipient, 
                0,
                SwapCallbackData({
                    path: params.path2, 
                    payer: address(this) 
                })
            );
        }

        require(amountOut >= params.amountOutMinimum, 'SwapX: too little received');
    }

    // Mixed: ExactOut multi-hop 
    function swapMixedMultiHopExactOut(
        ExactOutputMixedParams memory params
    ) external payable nonReentrant whenNotPaused checkDeadline(params.deadline) returns (uint256 amountIn) {

        require(params.amountInMaximum > 0, "SwapX: amount in max is zero");
        if (msg.value > 0)
            require(msg.value >= params.amountInMaximum, "SwapX: amount in max and value mismatch");

        (address tokenIn, address tokenOut1,) = params.path1.decodeFirstPool();
        (, address tokenOut,) = params.path2.decodeFirstPool();

        if (isStrEqual(params.routes[0], "v2") && isStrEqual(params.routes[1], "v2")) {
            // uni - sushi, or verse
            address poolAddress1 = UniswapV2Library.pairFor(params.factory1, tokenIn, tokenOut1);

            address poolAddress2 = UniswapV2Library.pairFor(params.factory2, tokenOut1, tokenOut);
            address[] memory path2 = new address[](2);
            path2[0] = tokenOut1;
            path2[1] = tokenOut;
            uint[] memory amounts2 = UniswapV2Library.getAmountsIn(params.factory2, params.amountOut, path2);

            address[] memory path1 = new address[](2);
            path1[0] = tokenIn;
            path1[1] = tokenOut1;
            uint[] memory amounts1 = UniswapV2Library.getAmountsIn(params.factory1, amounts2[0], path1);
            amountIn = amounts1[0];

            if (tokenIn == WETH) {
                pay(tokenIn, address(this), poolAddress1, amountIn);
            } else
                pay(tokenIn, msg.sender, poolAddress1, amountIn);

            _swap(amounts1, path1, poolAddress2, params.factory1);

            _swap(amounts2, path2, params.recipient, params.factory2);

        } else if (isStrEqual(params.routes[0], "v2") && isStrEqual(params.routes[1], "v3")) {
            // NOTE: v3 not support fee-on-transfer token, so the mid-token amountIn is exactly same as params.amountIn2 
            // v3 path bytes is reversed
            (tokenOut, ,) = params.path2.decodeFirstPool();

            address poolAddress1 = UniswapV2Library.pairFor(params.factory1, tokenIn, tokenOut1);
            address[] memory path1 = new address[](2);
            path1[0] = tokenIn;
            path1[1] = tokenOut1;
            uint[] memory amounts1 = UniswapV2Library.getAmountsIn(params.factory1, params.amountIn2, path1);
            amountIn = amounts1[0];
            if (tokenIn == WETH) {
                pay(tokenIn, address(this), poolAddress1, amountIn);
            } else
                pay(tokenIn, msg.sender, poolAddress1, amountIn);

            _swap(amounts1, path1, address(this), params.factory1);

            uint amountIn2 = exactOutputInternal(
                params.amountOut,
                params.recipient,
                0,
                SwapCallbackData({path: params.path2, payer: address(this)})
            );
            require(amountIn2 == params.amountIn2, "SwapX: not support fee-on-transfer token for V3");

        } else if (isStrEqual(params.routes[0], "v3") && isStrEqual(params.routes[1], "v2")) {

            (tokenOut1, tokenIn,) = params.path1.decodeFirstPool();

            address[] memory path2 = new address[](2); 
            path2[0] = tokenOut1;
            path2[1] = tokenOut;
            address poolAddress1 = UniswapV2Library.pairFor(params.factory2, tokenOut1, tokenOut);
            uint[] memory amounts2 = UniswapV2Library.getAmountsIn(params.factory2, params.amountOut, path2);
            uint amountIn2 = amounts2[0];

            amountIn = exactOutputInternal(
                amountIn2,
                poolAddress1,
                0,
                SwapCallbackData({path: params.path1, payer: msg.sender})
            );

            _swap(amounts2, path2, params.recipient, params.factory2);
        } 

        uint256 fee = takeFee(tokenIn, amountIn);
        require(amountIn + fee <= params.amountInMaximum, "SwapX: too much requested");

        if (msg.value > 0) {
          uint amount = msg.value - amountIn - fee;
          // refund
          if (amount > 0) {
              (bool success, ) = address(msg.sender).call{value: amount}("");
              require(success, "SwapX: refund ETH error");
          }
        }
    }

    // V3: compute pool address
    function getPool(
        address tokenA,
        address tokenB,
        uint24 fee
    ) public view returns (IUniswapV3Pool) {
        return IUniswapV3Pool(PoolAddress.computeAddress(factoryV3, PoolAddress.getPoolKey(tokenA, tokenB, fee)));
    }

    /// V3: Performs a single exact input swap
    function exactInputInternal(
        uint256 amountIn,
        address recipient,
        uint160 sqrtPriceLimitX96,
        SwapCallbackData memory data
    ) private returns (uint256 amountOut) {
        // allow swapping to the router address with address 0
        if (recipient == address(0)) recipient = address(this);

        (address tokenIn, address tokenOut, uint24 fee) = data.path.decodeFirstPool();

        bool zeroForOne = tokenIn < tokenOut;

        (int256 amount0, int256 amount1) =
            getPool(tokenIn, tokenOut, fee).swap(
                recipient,
                zeroForOne,
                amountIn.toInt256(),
                sqrtPriceLimitX96 == 0
                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)
                    : sqrtPriceLimitX96,
                abi.encode(data)
            );

        return uint256(-(zeroForOne ? amount1 : amount0));
    }

    /// Performs a single exact output swap
    function exactOutputInternal(
        uint256 amountOut,
        address recipient,
        uint160 sqrtPriceLimitX96,
        SwapCallbackData memory data
    ) private returns (uint256 amountIn) {
        // allow swapping to the router address with address 0
        if (recipient == address(0)) recipient = address(this);

        (address tokenOut, address tokenIn, uint24 fee) = data.path.decodeFirstPool();

        bool zeroForOne = tokenIn < tokenOut;

        (int256 amount0Delta, int256 amount1Delta) =
            getPool(tokenIn, tokenOut, fee).swap(
                recipient,
                zeroForOne,
                -amountOut.toInt256(),
                sqrtPriceLimitX96 == 0
                    ? (zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1)
                    : sqrtPriceLimitX96,
                abi.encode(data)
            );

        uint256 amountOutReceived;
        (amountIn, amountOutReceived) = zeroForOne
            ? (uint256(amount0Delta), uint256(-amount1Delta))
            : (uint256(amount1Delta), uint256(-amount0Delta));
        // it's technically possible to not receive the full output amount,
        // so if no price limit has been specified, require this possibility away
        if (sqrtPriceLimitX96 == 0) require(amountOutReceived == amountOut);
    }

    function pay(
        address token,
        address payer,
        address recipient,
        uint256 value
    ) internal {
        if (token == WETH && address(this).balance >= value) {
            // pay with WETH
            IWETH(WETH).deposit{value: value}(); // wrap only what is needed to pay
            IWETH(WETH).transfer(recipient, value);
        } else if (payer == address(this)) {
            // pay with tokens already in the contract (for the exact input multihop case)
            IERC20Upgradeable(token).safeTransfer(recipient, value);
        } else {
            // pull payment
            IERC20Upgradeable(token).safeTransferFrom(payer, recipient, value);
        }
    }

    function pause() external onlyOwner {
        _pause();
    }

    function unpause() external onlyOwner {
        _unpause();
    }

    function setFeeRate(uint256 rate) external onlyOwner {
        require(rate < 10000, "rate over feeDenominator");
        feeRate = rate;
    }

    function setFeeCollector(address addr) external onlyOwner {
        require(addr != address(0), "invalid addr");
        feeCollector = addr;
    }

    function setWETH(address addr) external onlyOwner {
        require(addr != address(0), "invalid addr");
        WETH = addr;
    }

    function setFeeExclude(address addr, bool isExcluded) external onlyOwner {
        require(addr != address(0), "invalid addr");
        feeExcludeList[addr] = isExcluded;
    }

    function rescueERC20Token(address token, address recipient) external onlyOwner {
        require(recipient!= address(0), "invalid addr");
        IERC20Upgradeable(token).safeTransfer(recipient, IERC20Upgradeable(token).balanceOf(address(this)));
    }
}

File 2 of 22 : Storage.sol
// SPDX-License-Identifier: MIT

pragma solidity >= 0.8.0;

contract Storage  {
    uint256 public amountInCached;
    uint256 public feeRate;
    uint256 public feeDenominator;
    address public feeCollector;
    address public WETH;
    address public factoryV2;
    address public factoryV3;

    mapping (address => bool) public feeExcludeList;
}

File 3 of 22 : IUniswapV3SwapCallback.sol
// SPDX-License-Identifier: MIT 
pragma solidity >=0.5.0;

interface IUniswapV3SwapCallback {
    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
    /// @dev In the implementation you must pay the pool tokens owed for the swap.
    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
    function uniswapV3SwapCallback(
        int256 amount0Delta,
        int256 amount1Delta,
        bytes calldata data
    ) external;
}

File 4 of 22 : IUniswapV3Pool.sol
// SPDX-License-Identifier: MIT

pragma solidity >= 0.5.0;

interface IUniswapV3Pool {

    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface
    /// @return The contract address
    function factory() external view returns (address);

    /// @notice The first of the two tokens of the pool, sorted by address
    /// @return The token contract address
    function token0() external view returns (address);

    /// @notice The second of the two tokens of the pool, sorted by address
    /// @return The token contract address
    function token1() external view returns (address);

    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6
    /// @return The fee
    function fee() external view returns (uint24);
    
    function swap(
        address recipient,
        bool zeroForOne,
        int256 amountSpecified,
        uint160 sqrtPriceLimitX96,
        bytes calldata data
    ) external returns (int256 amount0, int256 amount1);
}

File 5 of 22 : IUniswapV2Pair.sol
// SPDX-License-Identifier: MIT

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 6 of 22 : CallbackValidation.sol
// SPDX-License-Identifier: MIT 
pragma solidity >=0.7.6;

import '../interfaces/IUniswapV3Pool.sol';
import './PoolAddress.sol';

/// @notice Provides validation for callbacks from Uniswap V3 Pools
library CallbackValidation {
    /// @notice Returns the address of a valid Uniswap V3 Pool
    /// @param factory The contract address of the Uniswap V3 factory
    /// @param tokenA The contract address of either token0 or token1
    /// @param tokenB The contract address of the other token
    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip
    /// @return pool The V3 pool contract address
    function verifyCallback(
        address factory,
        address tokenA,
        address tokenB,
        uint24 fee
    ) internal view returns (IUniswapV3Pool pool) {
        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));
    }

    /// @notice Returns the address of a valid Uniswap V3 Pool
    /// @param factory The contract address of the Uniswap V3 factory
    /// @param poolKey The identifying key of the V3 pool
    /// @return pool The V3 pool contract address
    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)
        internal
        view
        returns (IUniswapV3Pool pool)
    {
        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));
        require(msg.sender == address(pool));
    }
}

File 7 of 22 : UniswapV2Library.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.5.0;

import '../interfaces/IUniswapV2Pair.sol';

import "../utils/SafeMath.sol";

library UniswapV2Library {
    using SafeMath for uint;

    // 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) internal pure returns (address pair) {
        (address token0, address token1) = sortTokens(tokenA, tokenB);
        if (factory == address(0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f)) {
          bytes32 pubKey = keccak256(abi.encodePacked(
                  hex'ff',
                  factory,
                  keccak256(abi.encodePacked(token0, token1)),
                  hex'96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f' // init code hash
              ));
          assembly {
              mstore(0x0, pubKey)
              pair := mload(0x0)
          }
        } else {
          bytes32 pubKey = keccak256(abi.encodePacked(
                  hex'ff',
                  factory,
                  keccak256(abi.encodePacked(token0, token1)),
                  hex'e18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303' // init code hash
              ));
          assembly {
              mstore(0x0, pubKey)
              pair := mload(0x0)
          }
        }
    }

    // fetches and sorts the reserves for a pair
    function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) {
        (address token0,) = sortTokens(tokenA, tokenB);
        (uint reserve0, uint reserve1,) = IUniswapV2Pair(pairFor(factory, tokenA, tokenB)).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(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint 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(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {
        require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT');
        require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
        uint amountInWithFee = amountIn.mul(997);
        uint numerator = amountInWithFee.mul(reserveOut);
        uint 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(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) {
        require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT');
        require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY');
        uint numerator = reserveIn.mul(amountOut).mul(1000);
        uint denominator = reserveOut.sub(amountOut).mul(997);
        amountIn = (numerator / denominator).add(1);
    }

    // performs chained getAmountOut calculations on any number of pairs
    function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) {
        require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');
        amounts = new uint[](path.length);
        amounts[0] = amountIn;
        for (uint i; i < path.length - 1; i++) {
            (uint reserveIn, uint reserveOut) = getReserves(factory, path[i], path[i + 1]);
            amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
        }
    }

    // performs chained getAmountIn calculations on any number of pairs
    function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) {
        require(path.length >= 2, 'UniswapV2Library: INVALID_PATH');
        amounts = new uint[](path.length);
        amounts[amounts.length - 1] = amountOut;
        for (uint i = path.length - 1; i > 0; i--) {
            (uint reserveIn, uint reserveOut) = getReserves(factory, path[i - 1], path[i]);
            amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
        }
    }
}

File 8 of 22 : SafeCast.sol
// SPDX-License-Identifier: MIT 
pragma solidity >=0.5.0;

/// @title Safe casting methods
/// @notice Contains methods for safely casting between types
library SafeCast {
    /// @notice Cast a uint256 to a uint160, revert on overflow
    /// @param y The uint256 to be downcasted
    /// @return z The downcasted integer, now type uint160
    function toUint160(uint256 y) internal pure returns (uint160 z) {
        require((z = uint160(y)) == y);
    }

    /// @notice Cast a int256 to a int128, revert on overflow or underflow
    /// @param y The int256 to be downcasted
    /// @return z The downcasted integer, now type int128
    function toInt128(int256 y) internal pure returns (int128 z) {
        require((z = int128(y)) == y);
    }

    /// @notice Cast a uint256 to a int256, revert on overflow
    /// @param y The uint256 to be casted
    /// @return z The casted integer, now type int256
    function toInt256(uint256 y) internal pure returns (int256 z) {
        require(y < 2**255);
        z = int256(y);
    }
}

File 9 of 22 : TickMath.sol
// SPDX-License-Identifier: MIT 
pragma solidity >=0.5.0;

/// @title Math library for computing sqrt prices from ticks and vice versa
/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports
/// prices between 2**-128 and 2**128
library TickMath {
    /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128
    int24 internal constant MIN_TICK = -887272;
    /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128
    int24 internal constant MAX_TICK = -MIN_TICK;

    /// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)
    uint160 internal constant MIN_SQRT_RATIO = 4295128739;
    /// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)
    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;

    /// @notice Calculates sqrt(1.0001^tick) * 2^96
    /// @dev Throws if |tick| > max tick
    /// @param tick The input tick for the above formula
    /// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)
    /// at the given tick
    function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
        uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));
        require(absTick <= toUint256(MAX_TICK), 'T');

        uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;
        if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
        if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
        if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
        if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
        if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
        if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
        if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
        if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
        if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
        if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
        if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
        if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
        if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
        if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
        if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
        if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
        if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
        if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
        if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;

        if (tick > 0) ratio = type(uint256).max / ratio;

        // this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.
        // we then downcast because we know the result always fits within 160 bits due to our tick input constraint
        // we round up in the division so getTickAtSqrtRatio of the output price is always consistent
        sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));
    }

    /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio
    /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may
    /// ever return.
    /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96
    /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio
    function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {
        // second inequality must be < because the price can never reach the price at the max tick
        require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');
        uint256 ratio = uint256(sqrtPriceX96) << 32;

        uint256 r = ratio;
        uint256 msb = 0;

        assembly {
            let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := shl(5, gt(r, 0xFFFFFFFF))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := shl(4, gt(r, 0xFFFF))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := shl(3, gt(r, 0xFF))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := shl(2, gt(r, 0xF))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := shl(1, gt(r, 0x3))
            msb := or(msb, f)
            r := shr(f, r)
        }
        assembly {
            let f := gt(r, 0x1)
            msb := or(msb, f)
        }

        if (msb >= 128) r = ratio >> (msb - 127);
        else r = ratio << (127 - msb);

        int256 log_2 = (int256(msb) - 128) << 64;

        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(63, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(62, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(61, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(60, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(59, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(58, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(57, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(56, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(55, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(54, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(53, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(52, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(51, f))
            r := shr(f, r)
        }
        assembly {
            r := shr(127, mul(r, r))
            let f := shr(128, r)
            log_2 := or(log_2, shl(50, f))
        }

        int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number

        int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);
        int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);

        tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;
    }

    function toUint256(int24 value) pure public returns (uint256) {
        require(value >= 0, "Input value is negative");

        int256 convertedInt = int256(value);
        return uint256(convertedInt);
    }
}

File 10 of 22 : Path.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.0;

import './BytesLib.sol';

/// @title Functions for manipulating path data for multihop swaps
library Path {
    using BytesLib for bytes;

    /// @dev The length of the bytes encoded address
    uint256 private constant ADDR_SIZE = 20;
    /// @dev The length of the bytes encoded fee
    uint256 private constant FEE_SIZE = 3;

    /// @dev The offset of a single token address and pool fee
    uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;
    /// @dev The offset of an encoded pool key
    uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;
    /// @dev The minimum length of an encoding that contains 2 or more pools
    uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;

    /// @notice Returns true iff the path contains two or more pools
    /// @param path The encoded swap path
    /// @return True if path contains two or more pools, otherwise false
    function hasMultiplePools(bytes memory path) internal pure returns (bool) {
        return path.length >= MULTIPLE_POOLS_MIN_LENGTH;
    }

    /// @notice Returns the number of pools in the path
    /// @param path The encoded swap path
    /// @return The number of pools in the path
    function numPools(bytes memory path) internal pure returns (uint256) {
        // Ignore the first token address. From then on every fee and token offset indicates a pool.
        return ((path.length - ADDR_SIZE) / NEXT_OFFSET);
    }

    /// @notice Decodes the first pool in path
    /// @param path The bytes encoded swap path
    /// @return tokenA The first token of the given pool
    /// @return tokenB The second token of the given pool
    /// @return fee The fee level of the pool
    function decodeFirstPool(bytes memory path)
        internal
        pure
        returns (
            address tokenA,
            address tokenB,
            uint24 fee
        )
    {
        tokenA = path.toAddress(0);
        fee = path.toUint24(ADDR_SIZE);
        tokenB = path.toAddress(NEXT_OFFSET);
    }

    /// @notice Gets the segment corresponding to the first pool in the path
    /// @param path The bytes encoded swap path
    /// @return The segment containing all data necessary to target the first pool in the path
    function getFirstPool(bytes memory path) internal pure returns (bytes memory) {
        return path.slice(0, POP_OFFSET);
    }

    /// @notice Skips a token + fee element from the buffer and returns the remainder
    /// @param path The swap path
    /// @return The remaining token + fee elements in the path
    function skipToken(bytes memory path) internal pure returns (bytes memory) {
        return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);
    }
}

File 11 of 22 : SafeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.6.6;

// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)

library SafeMath {
    function add(uint x, uint y) internal pure returns (uint z) {
        require((z = x + y) >= x, 'ds-math-add-overflow');
    }

    function sub(uint x, uint y) internal pure returns (uint z) {
        require((z = x - y) <= x, 'ds-math-sub-underflow');
    }

    function mul(uint x, uint y) internal pure returns (uint z) {
        require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
    }

    function div(uint a, uint b) internal pure returns (uint) {
        assert(b > 0); // Solidity automatically throws when dividing by 0
        // uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold
        return a / b;
    }

}

File 12 of 22 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.20;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Storage of the initializable contract.
     *
     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
     * when using with upgradeable contracts.
     *
     * @custom:storage-location erc7201:openzeppelin.storage.Initializable
     */
    struct InitializableStorage {
        /**
         * @dev Indicates that the contract has been initialized.
         */
        uint64 _initialized;
        /**
         * @dev Indicates that the contract is in the process of being initialized.
         */
        bool _initializing;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1))
    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0e;

    /**
     * @dev The contract is already initialized.
     */
    error AlreadyInitialized();

    /**
     * @dev The contract is not initializing.
     */
    error NotInitializing();

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint64 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
     * constructor.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        bool isTopLevelCall = !$._initializing;
        uint64 initialized = $._initialized;
        if (!(isTopLevelCall && initialized < 1) && !(address(this).code.length == 0 && initialized == 1)) {
            revert AlreadyInitialized();
        }
        $._initialized = 1;
        if (isTopLevelCall) {
            $._initializing = true;
        }
        _;
        if (isTopLevelCall) {
            $._initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: setting the version to 255 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint64 version) {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing || $._initialized >= version) {
            revert AlreadyInitialized();
        }
        $._initialized = version;
        $._initializing = true;
        _;
        $._initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        _checkInitializing();
        _;
    }

    /**
     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
     */
    function _checkInitializing() internal view virtual {
        if (!_isInitializing()) {
            revert NotInitializing();
        }
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing) {
            revert AlreadyInitialized();
        }
        if ($._initialized != type(uint64).max) {
            $._initialized = type(uint64).max;
            emit Initialized(type(uint64).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint64) {
        return _getInitializableStorage()._initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _getInitializableStorage()._initializing;
    }

    /**
     * @dev Returns a pointer to the storage namespace.
     */
    // solhint-disable-next-line var-name-mixedcase
    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
        assembly {
            $.slot := INITIALIZABLE_STORAGE
        }
    }
}

File 13 of 22 : OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import { ContextUpgradeable } from "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    function __Ownable_init(address initialOwner) internal onlyInitializing {
        __Ownable_init_unchained(initialOwner);
    }

    function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;
}

File 14 of 22 : SafeERC20Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import { IERC20Upgradeable } from "../IERC20Upgradeable.sol";
import { IERC20PermitUpgradeable } from "../extensions/IERC20PermitUpgradeable.sol";
import { AddressUpgradeable } from "../../../utils/AddressUpgradeable.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 SafeERC20Upgradeable {
    using AddressUpgradeable for address;

    /**
     * @dev An operation with an ERC20 token failed.
     */
    error SafeERC20FailedOperation(address token);

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20Upgradeable token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    function safePermit(
        IERC20PermitUpgradeable token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        if (nonceAfter != nonceBefore + 1) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @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(IERC20Upgradeable 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);
        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
    }
}

File 15 of 22 : IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20Upgradeable {
    /**
     * @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 value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` 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 value) external returns (bool);
}

File 16 of 22 : ReentrancyGuardUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.20;
import "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuardUpgradeable is Initializable {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    function __ReentrancyGuard_init() internal onlyInitializing {
        __ReentrancyGuard_init_unchained();
    }

    function __ReentrancyGuard_init_unchained() internal onlyInitializing {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;
}

File 17 of 22 : PausableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.20;

import { ContextUpgradeable } from "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
    bool private _paused;

    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    /**
     * @dev The operation failed because the contract is paused.
     */
    error EnforcedPause();

    /**
     * @dev The operation failed because the contract is not paused.
     */
    error ExpectedPause();

    /**
     * @dev Initializes the contract in unpaused state.
     */
    function __Pausable_init() internal onlyInitializing {
        __Pausable_init_unchained();
    }

    function __Pausable_init_unchained() internal onlyInitializing {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        if (paused()) {
            revert EnforcedPause();
        }
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        if (!paused()) {
            revert ExpectedPause();
        }
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[49] private __gap;
}

File 18 of 22 : BytesLib.sol
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * @title Solidity Bytes Arrays Utils
 * @author Gonçalo Sá <[email protected]>
 *
 * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
 *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
 */
pragma solidity >=0.5.0 <0.9.0;

library BytesLib {
    function slice(
        bytes memory _bytes,
        uint256 _start,
        uint256 _length
    ) internal pure returns (bytes memory) {
        require(_length + 31 >= _length, 'slice_overflow');
        require(_start + _length >= _start, 'slice_overflow');
        require(_bytes.length >= _start + _length, 'slice_outOfBounds');

        bytes memory tempBytes;

        assembly {
            switch iszero(_length)
                case 0 {
                    // Get a location of some free memory and store it in tempBytes as
                    // Solidity does for memory variables.
                    tempBytes := mload(0x40)

                    // The first word of the slice result is potentially a partial
                    // word read from the original array. To read it, we calculate
                    // the length of that partial word and start copying that many
                    // bytes into the array. The first word we copy will start with
                    // data we don't care about, but the last `lengthmod` bytes will
                    // land at the beginning of the contents of the new array. When
                    // we're done copying, we overwrite the full first word with
                    // the actual length of the slice.
                    let lengthmod := and(_length, 31)

                    // The multiplication in the next line is necessary
                    // because when slicing multiples of 32 bytes (lengthmod == 0)
                    // the following copy loop was copying the origin's length
                    // and then ending prematurely not copying everything it should.
                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                    let end := add(mc, _length)

                    for {
                        // The multiplication in the next line has the same exact purpose
                        // as the one above.
                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                    } lt(mc, end) {
                        mc := add(mc, 0x20)
                        cc := add(cc, 0x20)
                    } {
                        mstore(mc, mload(cc))
                    }

                    mstore(tempBytes, _length)

                    //update free-memory pointer
                    //allocating the array padded to 32 bytes like the compiler does now
                    mstore(0x40, and(add(mc, 31), not(31)))
                }
                //if we want a zero-length slice let's just return a zero-length array
                default {
                    tempBytes := mload(0x40)
                    //zero out the 32 bytes slice we are about to return
                    //we need to do it because Solidity does not garbage collect
                    mstore(tempBytes, 0)

                    mstore(0x40, add(tempBytes, 0x20))
                }
        }

        return tempBytes;
    }

    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
        require(_start + 20 >= _start, 'toAddress_overflow');
        require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }

    function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) {
        require(_start + 3 >= _start, 'toUint24_overflow');
        require(_bytes.length >= _start + 3, 'toUint24_outOfBounds');
        uint24 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x3), _start))
        }

        return tempUint;
    }
}

File 19 of 22 : PoolAddress.sol
// SPDX-License-Identifier: MIT 
pragma solidity >=0.5.0;

/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee
library PoolAddress {
    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;

    /// @notice The identifying key of the pool
    struct PoolKey {
        address token0;
        address token1;
        uint24 fee;
    }

    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels
    /// @param tokenA The first token of a pool, unsorted
    /// @param tokenB The second token of a pool, unsorted
    /// @param fee The fee level of the pool
    /// @return Poolkey The pool details with ordered token0 and token1 assignments
    function getPoolKey(
        address tokenA,
        address tokenB,
        uint24 fee
    ) internal pure returns (PoolKey memory) {
        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);
        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});
    }

    /// @notice Deterministically computes the pool address given the factory and PoolKey
    /// @param factory The Uniswap V3 factory contract address
    /// @param key The PoolKey
    /// @return pool The contract address of the V3 pool
    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {
        require(key.token0 < key.token1);
        bytes32 pubKey = 
                keccak256(
                    abi.encodePacked(
                        hex'ff',
                        factory,
                        keccak256(abi.encode(key.token0, key.token1, key.fee)),
                        POOL_INIT_CODE_HASH
                    )
                );
        // bytes32 to address:
        assembly {
            mstore(0x0, pubKey)
            pool := mload(0x0)
        }
    }
}

File 20 of 22 : AddressUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedInnerCall();

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert AddressInsufficientBalance(address(this));
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert FailedInnerCall();
        }
    }

    /**
     * @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 or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {FailedInnerCall} error.
     *
     * 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.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @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`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
     * unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {FailedInnerCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
     */
    function _revert(bytes memory returndata) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert FailedInnerCall();
        }
    }
}

File 21 of 22 : IERC20PermitUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20PermitUpgradeable {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 22 of 22 : ContextUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.20;
import "../proxy/utils/Initializable.sol";

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract ContextUpgradeable is Initializable {
    function __Context_init() internal onlyInitializing {
    }

    function __Context_init_unchained() internal onlyInitializing {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    /**
     * @dev This empty reserved space is put in place to allow future versions to add new
     * variables without shifting down storage in the inheritance chain.
     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
     */
    uint256[50] private __gap;
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "viaIR": true,
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "remappings": []
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"payer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"FeeCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"amountInCached","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factoryV2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factoryV3","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeDenominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"feeExcludeList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"}],"name":"getPool","outputs":[{"internalType":"contract IUniswapV3Pool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_factoryV2","type":"address"},{"internalType":"address","name":"_factoryV3","type":"address"},{"internalType":"address","name":"_WETH","type":"address"},{"internalType":"address","name":"_feeCollector","type":"address"},{"internalType":"uint256","name":"_feeRate","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"recipient","type":"address"}],"name":"rescueERC20Token","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"setFeeExclude","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"rate","type":"uint256"}],"name":"setFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setWETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string[]","name":"routes","type":"string[]"},{"internalType":"bytes","name":"path1","type":"bytes"},{"internalType":"address","name":"factory1","type":"address"},{"internalType":"bytes","name":"path2","type":"bytes"},{"internalType":"address","name":"factory2","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"}],"internalType":"struct SwapX.ExactInputMixedParams","name":"params","type":"tuple"}],"name":"swapMixedMultiHopExactIn","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"string[]","name":"routes","type":"string[]"},{"internalType":"bytes","name":"path1","type":"bytes"},{"internalType":"address","name":"factory1","type":"address"},{"internalType":"bytes","name":"path2","type":"bytes"},{"internalType":"address","name":"factory2","type":"address"},{"internalType":"uint256","name":"amountIn2","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"}],"internalType":"struct SwapX.ExactOutputMixedParams","name":"params","type":"tuple"}],"name":"swapMixedMultiHopExactOut","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address","name":"poolAddress","type":"address"}],"name":"swapV2ExactIn","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"poolAddress","type":"address"}],"name":"swapV2ExactOut","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"factory","type":"address"}],"name":"swapV2MultiHopExactIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"factory","type":"address"}],"name":"swapV2MultiHopExactOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"internalType":"struct SwapX.ExactInputSingleParams","name":"params","type":"tuple"}],"name":"swapV3ExactIn","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"},{"internalType":"uint160","name":"sqrtPriceLimitX96","type":"uint160"}],"internalType":"struct SwapX.ExactOutputSingleParams","name":"params","type":"tuple"}],"name":"swapV3ExactOut","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"}],"internalType":"struct SwapX.ExactInputParams","name":"params","type":"tuple"}],"name":"swapV3MultiHopExactIn","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"}],"internalType":"struct SwapX.ExactOutputParams","name":"params","type":"tuple"}],"name":"swapV3MultiHopExactOut","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"amount0Delta","type":"int256"},{"internalType":"int256","name":"amount1Delta","type":"int256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"uniswapV3SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60808060405234601557615281908161001a8239f35b5f80fdfe6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c8063130e594c146102195780631698ee8214610214578063180b0d7e1461020f5780631d5f45f51461020a5780633f4ba83a1461020557806345596e2e14610200578063472798df146101fb57806358e3ce30146101f65780635a4882d1146101f15780635b769f3c146101ec5780635b9e9006146101e75780635c975abb146101e257806366a5a99e146101dd57806368e0d4e1146101d8578063715018a6146101d35780638456cb59146101ce5780638d7f6c3a146101c95780638da5cb5b146101c45780639036f625146101bf578063936c044b146101ba578063978bbdb9146101b5578063a14bef8f146101b0578063a42dce80146101ab578063a7d14ad2146101a6578063ad5c4648146101a1578063bfc60df91461019c578063c415b95c14610197578063d5e4098314610192578063f2fde38b1461018d578063f7013ef614610188578063f83bda78146101835763fa461e330361000e57612070565b611fc5565b611e17565b611dc7565b611c6f565b611c47565b611c07565b611bdf565b61199d565b61194d565b611838565b61181b565b6117b7565b611713565b6116eb565b611406565b6113ad565b611352565b61132a565b611090565b610fb8565b610b2f565b610aa5565b6109ec565b6109d0565b610751565b610664565b6105fe565b6105d6565b6105b9565b610558565b61042b565b634e487b7160e01b5f52604160045260245ffd5b61010081019081106001600160401b0382111761024e57604052565b61021e565b60a081019081106001600160401b0382111761024e57604052565b60c081019081106001600160401b0382111761024e57604052565b606081019081106001600160401b0382111761024e57604052565b90601f801991011681019081106001600160401b0382111761024e57604052565b604051906102d5610120836102a4565b565b604051906102d56040836102a4565b604051906102d5610140836102a4565b6001600160401b03811161024e5760051b60200190565b6001600160401b03811161024e57601f01601f191660200190565b9291926103348261030d565b9161034260405193846102a4565b82948184528183011161035e578281602093845f960137010152565b5f80fd5b81601f8201121561035e57803590610379826102f6565b9261038760405194856102a4565b82845260208085019360051b8301019181831161035e5760208101935b8385106103b357505050505090565b84356001600160401b03811161035e57820183603f8201121561035e576020916103e68583604086809601359101610328565b8152019401936103a4565b9080601f8301121561035e5781602061040c93359101610328565b90565b6001600160a01b0381160361035e57565b35906102d58261040f565b602036600319011261035e576004356001600160401b03811161035e57610120600319823603011261035e5761045f6102c5565b9080600401356001600160401b03811161035e576104839060043691840101610362565b825260248101356001600160401b03811161035e576104a890600436918401016103f1565b60208301526104b960448201610420565b60408301526064810135916001600160401b03831161035e57610104610534926104ec61054495600436918401016103f1565b60608401526104fd60848201610420565b608084015261050e60a48201610420565b60a084015260c481013560c084015260e481013560e084015201356101008201526120d0565b6040519081529081906020820190565b0390f35b359062ffffff8216820361035e57565b3461035e57606036600319011261035e576004356105758161040f565b602435906105828261040f565b60443562ffffff8116810361035e5760209261059d92612b72565b6040516001600160a01b039091168152f35b5f91031261035e57565b3461035e575f36600319011261035e576020600254604051908152f35b3461035e575f36600319011261035e576006546040516001600160a01b039091168152602090f35b3461035e575f36600319011261035e57610616614567565b609e5460ff8116156106555760ff1916609e557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b638dfc202b60e01b5f5260045ffd5b3461035e57602036600319011261035e57600435610680614567565b61271081101561068f57600155005b60405162461bcd60e51b815260206004820152601860248201527f72617465206f7665722066656544656e6f6d696e61746f7200000000000000006044820152606490fd5b61010090600319011261035e57604051906106ee82610232565b816106f96004610420565b81526107056024610420565b60208201526107146044610548565b60408201526107236064610420565b6060820152608435608082015260a43560a082015260c43560c082015260e061074c60e4610420565b910152565b61010036600319011261035e57610767366106d4565b61076f6139e1565b610777613a01565b6107876080820151421115612839565b60a08101610797815115156128c7565b81516001600160a01b03161561097f575b81516107ca906107c3906001600160a01b0316835190613ae0565b82516129a1565b81526020820180515f91906107ef906001600160a01b03165b6001600160a01b031690565b15610953575b61087b919251835f14610940575f5b60e08601516001600160a01b03168651909290610865906001600160a01b031661085761084861083a60408c015162ffffff1690565b97516001600160a01b031690565b60405197889360208501612ab3565b03601f1981018652856102a4565b61086d6102d7565b938452336020850152613d8e565b9061088c60c0840151831015612b9a565b61089f575b610544906105346001606c55565b6004546108b6906107e3906001600160a01b031681565b803b1561035e57604051632e1a7d4d60e01b815260048101839052905f908290602490829084905af1801561093b575f80808561090c60606105449961091c988598610921575b5001516001600160a01b031690565b5af16109166129ae565b50612be6565b610891565b8061092f87610935936102a4565b806105af565b5f6108fd565b612b1b565b60608501516001600160a01b0316610804565b60045461087b9250610976906001600160a01b03165b6001600160a01b03168252565b600191506107f5565b6004546001600160a01b0316825261099a8151341015612913565b6109a58151346129a1565b806109b1575b506107a8565b5f8080806109ca94335af16109c46129ae565b506129dd565b5f6109ab565b3461035e575f36600319011261035e5760205f54604051908152f35b3461035e57604036600319011261035e57600435610a098161040f565b60243590610a168261040f565b610a1e614567565b610a326001600160a01b0383161515612c32565b6040516370a0823160e01b8152306004820152916001600160a01b039190911690602083602481855afa91821561093b57610018935f93610a74575b5061458e565b610a9791935060203d602011610a9e575b610a8f81836102a4565b810190612b0c565b915f610a6e565b503d610a85565b3461035e57602036600319011261035e57600435610ac28161040f565b610aca614567565b6001600160a01b0316610ade811515612c32565b6001600160601b0360a01b60045416176004555f80f35b60a090600319011261035e57600435610b0d8161040f565b90602435610b1a8161040f565b90604435906064359060843561040c8161040f565b610b3836610af5565b610b439391936139e1565b610b4b613a01565b6001600160a01b038116928590610b63851515612c6d565b610b6e811515612cb9565b5f916001600160a01b031615610f63575b80610b8d610b939289613ae0565b906129a1565b9015610f5357610ba49130876142dd565b6001600160a01b0316905f908215610f4a575b8115610efa57600454610bd4906107e3906001600160a01b031681565b6040516370a0823160e01b815230600482015290602090829060249082905afa90811561093b575f91610edb575b50945b604051630dfe168160e01b8152602081600481865afa90811561093b575f91610eac575b50604051630240bc6b60e21b815291606083600481875afa92831561093b575f905f94610e6d575b506001600160a01b03918216929091168214926001600160701b0390811691168315610e67575b6040516370a0823160e01b81526001600160a01b038616600482015292602090849060249082905afa801561093b5781610cbd91610cc2955f91610de1575b506142bb565b614647565b9015610e60575f90915b8315610e595730905b610cdd612d64565b93813b1561035e575f8094610d086040519788968795869463022c0d9f60e01b865260048601612da3565b03925af1801561093b57610e45575b5015610e005750600454610d35906107e3906001600160a01b031681565b6040516370a0823160e01b81523060048201529092602082602481875afa801561093b57610d69925f91610de157506142bb565b90823b1561035e57604051632e1a7d4d60e01b815260048101839052925f908490602490829084905af190811561093b5761054493610dc392610dcd575b50610dbb5f80808087335af16109166129ae565b821015612dce565b6105346001606c55565b8061092f5f610ddb936102a4565b5f610da7565b610dfa915060203d602011610a9e57610a8f81836102a4565b5f610cb7565b6040516370a0823160e01b815233600482015290602090829060249082905afa90811561093b5761054493610dc392610e3f925f91610de157506142bb565b91610dbb565b8061092f5f610e53936102a4565b5f610d17565b3390610cd5565b5f91610ccc565b90610c78565b6001600160701b039450849150610e9b9060603d606011610ea5575b610e9381836102a4565b810190612d2e565b5094909150610c51565b503d610e89565b610ece915060203d602011610ed4575b610ec681836102a4565b810190612d05565b5f610c29565b503d610ebc565b610ef4915060203d602011610a9e57610a8f81836102a4565b5f610c02565b6040516370a0823160e01b8152336004820152602081602481875afa90811561093b575f91610f2b575b5094610c05565b610f44915060203d602011610a9e57610a8f81836102a4565b5f610f24565b60019150610bb7565b610f5e9133876142dd565b610ba4565b809650610f739150341015612913565b600454600190610b93906001600160a01b031696610f9181346129a1565b80610f9f575b509050610b7f565b5f808080610fb294335af16109c46129ae565b5f610f97565b3461035e575f36600319011261035e57602060ff609e54166040519015158152f35b60e060031982011261035e57600435610ff28161040f565b9160243591604435916064356001600160401b03811161035e578260238201121561035e578060040135926001600160401b03841161035e5760248460051b8301011161035e5760240191906110486084610420565b9060a4359061040c60c4610420565b60206040818301928281528451809452019201905f5b81811061107a5750505090565b825184526020938401939092019160010161106d565b61110e6110c96111646111526110a536610fda565b9895929a94979399906110b99792976139e1565b6110c1613a01565b421115612839565b898982936110d8811515612cb9565b5f936001600160a01b0316156112c6575b906111196110fe83610b8d6111209589613ae0565b978461111361110e8b9786612e24565b612e4c565b93612e2d565b908b613e50565b91156112b6576111319130846142dd565b6111416107e361110e8b8b612e24565b6001600160a01b0390911614612e56565b61115d368888612e91565b908561403f565b936111816107e36107e361110e61117a8a61297f565b8a86612e3c565b6040516370a0823160e01b81526001600160a01b03841660048201529290602090849060249082905afa91821561093b576112239588945f94611278575b506107e361110e6111f6936111e66107e394876111e160209a9b369086612e91565b6140d8565b8b6111f08161297f565b91612e3c565b6040516370a0823160e01b81526001600160a01b0390921660048301529094859190829081906024820190565b03915afa94851561093b5761125a61124c6112549361054498611262975f91610de157506142bb565b92839261297f565b86612a5f565b521015612dce565b61126c6001606c55565b60405191829182611057565b6020945061110e6111f6936111e66107e394876111e16112a76107e3978c3d8e11610a9e57610a8f81836102a4565b9a5050509450509350506111bf565b6112c19133846142dd565b611131565b93505050506112d781341015612913565b6001896111208a6111196110fe6112f560045460018060a01b031690565b9661130081346129a1565b80611311575b5092935050506110e9565b5f80808061132494335af16109c46129ae565b5f611306565b3461035e575f36600319011261035e576005546040516001600160a01b039091168152602090f35b3461035e575f36600319011261035e5761136a614567565b603a80546001600160a01b031981169091555f906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461035e575f36600319011261035e576113c5614567565b6113cd613a01565b600160ff19609e541617609e557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b61140f36610af5565b61141d9491949392936139e1565b611425613a01565b90926001600160a01b03821691908461143f841515612c6d565b61144a821515612ee7565b5f906001600160a01b0316156116c9575b5f946001600160a01b0316156116c0575b604051630dfe168160e01b815292602084600481885afa93841561093b575f9461169f575b50604051630240bc6b60e21b815293606085600481895afa94851561093b575f905f9661166b575b506001600160a01b03898116921691909114946114ea916001600160701b0391821691168615611665575b8a61477e565b96879261150c6114fa8584613ae0565b956115058787612f5d565b1115612f6a565b15611654579161152291611531949330906142dd565b61152c86346129a1565b6129a1565b8061163b575b505b15611633575f84915b831561162c5730905b611553612d64565b93813b1561035e575f809461157e6040519788968795869463022c0d9f60e01b865260048601612da3565b03925af1801561093b57611618575b506115a057610544906105346001606c55565b6004546115b7906107e3906001600160a01b031681565b803b1561035e57604051632e1a7d4d60e01b815260048101849052905f908290602490829084905af1801561093b575f80806105449661091c958295611604575b50335af16109166129ae565b8061092f84611612936102a4565b5f6115f8565b8061092f5f611626936102a4565b5f61158d565b339061154b565b835f91611542565b5f80808061164e94335af16109c46129ae565b5f611537565b611660935033906142dd565b611539565b906114e4565b6001600160701b0396506114ea929150611694879160603d606011610ea557610e9381836102a4565b5097509192506114b9565b6116b991945060203d602011610ed457610ec681836102a4565b925f611491565b6001945061146c565b506004546001600160a01b0316945060016116e634831115612913565b61145b565b3461035e575f36600319011261035e57603a546040516001600160a01b039091168152602090f35b602036600319011261035e576004356001600160401b03811161035e5760a0600319823603011261035e576040519061174b82610253565b8060040135916001600160401b03831161035e5760846105349261177861054495600436918401016103f1565b835260248101356117888161040f565b6020840152604481013560408401526064810135606084015201356080820152612fb6565b8015150361035e57565b3461035e57604036600319011261035e576004356117d48161040f565b602435906117e1826117ad565b6117e9614567565b6001600160a01b03166117fd811515612c32565b5f52600760205260405f209060ff8019835416911515161790555f80f35b3461035e575f36600319011261035e576020600154604051908152f35b602036600319011261035e576004356001600160401b03811161035e57610140600319823603011261035e5761186c6102e6565b9080600401356001600160401b03811161035e576118909060043691840101610362565b825260248101356001600160401b03811161035e576118b590600436918401016103f1565b60208301526118c660448201610420565b60408301526064810135916001600160401b03831161035e57610124610534926118f961054495600436918401016103f1565b606084015261190a60848201610420565b608084015260a481013560a084015261192560c48201610420565b60c084015260e481013560e084015261010481013561010084015201356101208201526130d0565b3461035e57602036600319011261035e5760043561196a8161040f565b611972614567565b6001600160a01b0316611986811515612c32565b6001600160601b0360a01b60035416176003555f80f35b61010036600319011261035e576119b3366106d4565b6119bb6139e1565b6119c3613a01565b6119d36080820151421115612839565b60c08101906119e48251151561357f565b80515f91906001600160a01b031615611bb4575b60208101805190935f91611a14906001600160a01b03166107e3565b15611b9d575b611a9060a0840195865190845f14611b8a575f5b60e0870151611a4f906001600160a01b03165b92516001600160a01b031690565b92611a7a611a6360408a015162ffffff1690565b8951909590610857906001600160a01b0316610848565b611a826102d7565b938452336020850152614b4e565b93611ac1611aad86611aa8875160018060a01b031690565b613ae0565b92611ab88488612f5d565b9051101561368b565b611b5d575b50611ad9575b5f195f5561054482610dc3565b600454611af0906107e3906001600160a01b031681565b92805193803b1561035e57604051632e1a7d4d60e01b815260048101959095525f908590602490829084905af193841561093b575f808093611b4a6060611b579784966105449b610921575001516001600160a01b031690565b9051905af16109166129ae565b5f611acc565b611b6b9061152c85346129a1565b8015611ac6575f808080611b8494335af16109c46129ae565b5f611ac6565b60608601516001600160a01b0316611a2e565b6004546001600160a01b0316855260019150611a1a565b60045460019250611bcd906001600160a01b0316610969565b611bda83513410156135cb565b6119f8565b3461035e575f36600319011261035e576004546040516001600160a01b039091168152602090f35b3461035e57602036600319011261035e57600435611c248161040f565b60018060a01b03165f526007602052602060ff60405f2054166040519015158152f35b3461035e575f36600319011261035e576003546040516001600160a01b039091168152602090f35b610544611c9a611262611d5e611cf1611c8736610fda565b9896919793959a906110b99593956139e1565b8091611ca78b151561357f565b5f916001600160a01b031615611d99575b611cd1611cf791611cca36888a612e91565b908b61497e565b9a6115058c611ce9611ce282612a3d565b5187613ae0565b968791612a3d565b51612f5d565b611d1b611d0761110e8688612e24565b611d1461110e8789612e2d565b908a613e50565b9015611d7d57611d4f9291611d3c91611d338c612a3d565b519130906142dd565b61152c611d488a612a3d565b51346129a1565b80611d64575b505b3691612e91565b84614c83565b5f808080611d7794335af16109c46129ae565b5f611d55565b611d949250611d8b8a612a3d565b519133906142dd565b611d57565b6004546001600160a01b0316925060019150611cf790611cd190611dbf348e1115612913565b915050611cb8565b3461035e57602036600319011261035e57600435611de48161040f565b611dec614567565b6001600160a01b03811615611e045761001890614736565b631e4fbdf760e01b5f525f60045260245ffd5b3461035e5760a036600319011261035e57600435611e348161040f565b60243590611e418261040f565b604435611e4d8161040f565b606435611e598161040f565b608435915f8051602061522c8339815191525494611e92611e85611e818860ff9060401c1690565b1590565b966001600160401b031690565b8680611fb2575b159081611f8b575b50611f7d57611ee49486611edb60016001600160401b03195f8051602061522c8339815191525416175f8051602061522c83398151915255565b611f43576136d7565b611eea57005b611f1460ff60401b195f8051602061522c83398151915254165f8051602061522c83398151915255565b604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b611f786801000000000000000060ff60401b195f8051602061522c8339815191525416175f8051602061522c83398151915255565b6136d7565b62dc149f60e41b5f5260045ffd5b303b15915081611f9e575b50155f611ea1565b600191506001600160401b0316145f611f96565b5060016001600160401b03821610611e99565b602036600319011261035e576004356001600160401b03811161035e5760c0600319823603011261035e5760405190611ffd8261026e565b8060040135916001600160401b03831161035e5760a46105349261202a61054495600436918401016103f1565b8352602481013561203a8161040f565b602084015261204b60448201610420565b60408401526064810135606084015260848101356080840152013560a082015261379b565b3461035e57606036600319011261035e576044356024356004356001600160401b03831161035e573660238401121561035e578260040135916001600160401b03831161035e57366024848601011161035e5760246100189401916138f1565b6120d86139e1565b6120e0613a01565b6120f060c0820151421115612839565b5f6120ff60028351511461287b565b60e0820161210f815115156128c7565b61211c6020840151613a1c565b919390925f9290916001600160a01b038616156127e7575b612149612142845188613ae0565b84516129a1565b83526121756121588851612a3d565b51612161612a73565b906020815191012090602081519101201490565b806127d4575b15612396575050926122739360408601926121a685846121a1875160018060a01b031690565b613e50565b9015612384576121b991519030846142dd565b6121dd6121c4612aea565b916121ce83612a3d565b6001600160a01b039091169052565b6121ea836121ce83612a4f565b6121f76060860151613a1c565b50939050612203612aea565b91612211826121ce85612a3d565b61221e856121ce85612a4f565b608087018051909261223b918791906001600160a01b0316613e50565b60a0880180516040516370a0823160e01b81526001600160a01b03918216600482015298971696909590602090899081906024820190565b03818a5afa97881561093b575f98612342575b50936122dc936122b1602097946122cf946122ab6123089b995160018060a01b031690565b916140d8565b83516122ab906001600160a01b03165b91516001600160a01b031690565b516001600160a01b031690565b6040516370a0823160e01b81526001600160a01b03909116600482015292839190829081906024820190565b03915afa90811561093b57612337926101009261232b925f91610de157506142bb565b925b0151821015612b26565b906102d56001606c55565b6123089795919850936122b1602097946122cf946122ab6123726122dc998c3d8e11610a9e57610a8f81836102a4565b9c95999b505094509497505093612286565b61239191519033846142dd565b6121b9565b6123a7612158889694959651612a3d565b806127c1575b1561256f57505061242461247f9461240894936124116124349460408a01966123e182866121a18b5160018060a01b031690565b901561255d5783516123f49130876142dd565b6123fc612aea565b9788946121ce86612a3d565b6121ce84612a4f565b84516001600160a01b031690519061403f565b61242e815161297f565b90612a5f565b51606085016124438151613a1c565b5060a0880180516040516370a0823160e01b81526001600160a01b03918216600482015298921696909590925090602090889081906024820190565b0381895afa96871561093b575f9761251d575b506124f495936122dc936124be602097946124b66124e6955160018060a01b031690565b9030906140d8565b83516001600160a01b03169051916124d46102d7565b9283523088840152613c68565b613c68565b50516001600160a01b031690565b03915afa90811561093b576123379261010092612517925f91610de157506142bb565b9261232d565b6124e6919750936122dc936124be602097946124b661254c6124f49b998b3d8d11610a9e57610a8f81836102a4565b9b9550509497505093509395612492565b835161256a9133876142dd565b6123f4565b90949192935061258b6125828751612a3d565b51612161612a93565b806127ae575b156126e75750612643612424608061261261267d97612626976121a1976125fc8c986125ee6125dc6125c660608d0151613a1c565b509c90809a8e92019e8f5160018060a01b031690565b94519360405196879360208501612ab3565b03601f1981018552846102a4565b6126046102d7565b928352336020840152613c68565b61261a612aea565b9687926121ce84612a3d565b612633856121ce84612a4f565b85516001600160a01b031661403f565b5060a0850180516040516370a0823160e01b81526001600160a01b0391821660048201529592169390929091602090869081906024820190565b0381875afa94851561093b575f956126b3575b50826122cf6124f495936122dc936122ab6122c16020985160018060a01b031690565b6122dc919550926122cf6124f495936126da602096873d8911610a9e57610a8f81836102a4565b9793509395505092612690565b949391906126f86125828651612a3d565b8061279b575b612713575b505050506101006123379161232d565b61233794955061279292849261274c6127649361273e61010098519360405195869360208501612ab3565b03601f1981018452836102a4565b6127546102d7565b9182523360208301523090613c68565b9081905260a08501516001600160a01b03166060860151916127846102d7565b928352306020840152613c68565b92915f80612703565b506127a96125828651612a4f565b6126fe565b506127bc6121588751612a4f565b612591565b506127cf6125828851612a4f565b6123ad565b506127e26121588851612a4f565b61217b565b945091506127f88151341015612913565b600454600192906001600160a01b0316946128148351346129a1565b80612820575b50612134565b5f80808061283394335af16109c46129ae565b5f61281a565b1561284057565b60405162461bcd60e51b8152602060048201526013602482015272151c985b9cd858dd1a5bdb881d1bdbc81bdb19606a1b6044820152606490fd5b1561288257565b60405162461bcd60e51b815260206004820152601e60248201527f53776170583a206f6e6c79203220726f7574657320737570706f7274656400006044820152606490fd5b156128ce57565b60405162461bcd60e51b815260206004820152601860248201527f53776170583a20616d6f756e7420696e206973207a65726f00000000000000006044820152606490fd5b1561291a57565b60405162461bcd60e51b815260206004820152602360248201527f53776170583a20616d6f756e7420696e20616e642076616c7565206d69736d616044820152620e8c6d60eb1b6064820152608490fd5b634e487b7160e01b5f52601160045260245ffd5b5f1981019190821161298d57565b61296b565b60011981019190821161298d57565b9190820391821161298d57565b3d156129d8573d906129bf8261030d565b916129cd60405193846102a4565b82523d5f602084013e565b606090565b156129e457565b60405162461bcd60e51b815260206004820152601760248201527f53776170583a20726566756e6420455448206572726f720000000000000000006044820152606490fd5b634e487b7160e01b5f52603260045260245ffd5b805115612a4a5760200190565b612a29565b805160011015612a4a5760400190565b8051821015612a4a5760209160051b010190565b60405190612a826040836102a4565b60028252613b1960f11b6020830152565b60405190612aa26040836102a4565b6002825261763360f01b6020830152565b606091821b6001600160601b0319908116825260e89390931b6001600160e81b031916601482015292901b166017820152602b0190565b60405160609190612afb83826102a4565b6002815291601f1901366020840137565b9081602091031261035e575190565b6040513d5f823e3d90fd5b15612b2d57565b60405162461bcd60e51b815260206004820152601a60248201527f53776170583a20746f6f206c6974746c652072656365697665640000000000006044820152606490fd5b6006546001600160a01b0393612b969391851692612b909290614426565b90614489565b1690565b15612ba157565b60405162461bcd60e51b815260206004820152601e60248201527f53776170583a20696e73756666696369656e74206f757420616d6f756e7400006044820152606490fd5b15612bed57565b60405162461bcd60e51b815260206004820152601960248201527f53776170583a2073656e6420455448206f7574206572726f72000000000000006044820152606490fd5b15612c3957565b60405162461bcd60e51b815260206004820152600c60248201526b34b73b30b634b21030b2323960a11b6044820152606490fd5b15612c7457565b60405162461bcd60e51b815260206004820152601b60248201527f53776170583a20696e76616c696420706f6f6c206164647265737300000000006044820152606490fd5b15612cc057565b60405162461bcd60e51b815260206004820152601760248201527f53776170583a20616d6f757420696e206973207a65726f0000000000000000006044820152606490fd5b9081602091031261035e575161040c8161040f565b51906001600160701b038216820361035e57565b9081606091031261035e57612d4281612d1a565b916040612d5160208401612d1a565b92015163ffffffff8116810361035e5790565b60405190612d736020836102a4565b5f808352366020840137565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b909260809261040c95948352602083015260018060a01b031660408201528160608201520190612d7f565b15612dd557565b60405162461bcd60e51b815260206004820152602160248201527f53776170583a20696e73756666696369656e74206f757470757420616d6f756e6044820152601d60fa1b6064820152608490fd5b9015612a4a5790565b9060011015612a4a5760200190565b9190811015612a4a5760051b0190565b3561040c8161040f565b15612e5d57565b60405162461bcd60e51b815260206004820152600c60248201526b0d2dcecc2d8d2c840e0c2e8d60a31b6044820152606490fd5b929190612e9d816102f6565b93612eab60405195866102a4565b602085838152019160051b810192831161035e57905b828210612ecd57505050565b602080918335612edc8161040f565b815201910190612ec1565b15612eee57565b60405162461bcd60e51b815260206004820152601b60248201527f53776170583a20616d6f757420696e206d6178206973207a65726f00000000006044820152606490fd5b906001820180921161298d57565b906002820180921161298d57565b90601f820180921161298d57565b9190820180921161298d57565b15612f7157565b60405162461bcd60e51b815260206004820152601d60248201527f53776170583a2065786365737369766520696e70757420616d6f756e740000006044820152606490fd5b612fbe6139e1565b612fc6613a01565b612fd66040820151421115612839565b60608101612fe6815115156128c7565b34613093575b6130066107c3612ffc8451613a1c565b5050835190613ae0565b8152335b61305061301a8451516042111590565b918351835f1461307f5730905b6124e1613034885161483e565b9361303d6102d7565b9485526001600160a01b03166020850152565b808352901561306c57503061306583516148de565b835261300a565b6123379150608090920151821015612b26565b60208601516001600160a01b031690613027565b6130a08151341015612913565b6130ab8151346129a1565b806130b7575b50612fec565b5f8080806130ca94335af16109c46129ae565b5f6130b1565b6130d86139e1565b6130e0613a01565b6130f060e0820151421115612839565b5f6101208201906131038251151561357f565b341515908161356d575b6020840161311b8151613a1c565b509092606087019061312d8251613a1c565b5094905061313e6121588a51612a3d565b8061355a575b156132ff5750505060408601805190939061316b90839083906001600160a01b0316613e50565b916080880193818186516131849060018060a01b031690565b9161318e92613e50565b94613197612aea565b91836131a284612a3d565b6001600160a01b0390911690526131b883612a4f565b6001600160a01b03909116905280516001600160a01b0316826101008c01516131e09261497e565b916131e9612aea565b93856131f486612a3d565b6001600160a01b03909116905261320a85612a4f565b6001600160a01b0391821690528851168461322485612a3d565b5161322e9261497e565b97856132398a612a3d565b51600454909d8e998a926001600160a01b03166001600160a01b0316600160a01b600190038516145f149c6132a69c611aa89a6132b19f61329298611a419860c09861329897613292946132ef576122cf9230906142dd565b92614c83565b01516001600160a01b031690565b92611ab88486612f5d565b6132c2575b50906102d56001606c55565b6132d09061152c83346129a1565b80156132b6575f8080806132e994335af16109c46129ae565b5f6132b6565b6132fa9233906142dd565b6122cf565b6133126121588a97969394959751612a3d565b80613547575b1561344757505050805161332b90613a1c565b50505060408601805190929061334d90859083906001600160a01b0316613e50565b92613356612aea565b948261336187612a3d565b6001600160a01b03909116905261337786612a4f565b6001600160a01b03909116905280516001600160a01b031660a08901908682516133a09261497e565b946133aa86612a3d565b51600454909a8b96909187906001600160a01b03166001600160a01b03166132b19a6132a69a611aa8986134349761340695939492936133fe936001600160a01b038e160361343c576122cf91308e6142dd565b913091614c83565b61010082015160c0909201516001600160a01b03169051916134266102d7565b928352306020840152614a27565b905114613627565b6132fa91338e6142dd565b9197939450915061345b6125828451612a3d565b80613534575b613476575b5050506132a6846132b192613ae0565b60c096506132b193509061352e826134926132a6959451613a1c565b5093613292611a4161351e6134da6134a8612aea565b946134b6876121ce88612a3d565b6134c3816121ce88612a4f565b60808b0180519097906001600160a01b0316613e50565b85519096906134fa9086906001600160a01b03166101008d01519061497e565b9661350488612a3d565b519151916135106102d7565b928352336020840152614a27565b9c8d98015160018060a01b031690565b92613466565b506135426121588451612a4f565b613461565b506135556125828a51612a4f565b613318565b506135686121588a51612a4f565b613144565b61357a83513410156135cb565b61310d565b1561358657565b60405162461bcd60e51b815260206004820152601c60248201527f53776170583a20616d6f756e7420696e206d6178206973207a65726f000000006044820152606490fd5b156135d257565b60405162461bcd60e51b815260206004820152602760248201527f53776170583a20616d6f756e7420696e206d617820616e642076616c7565206d6044820152660d2e6dac2e8c6d60cb1b6064820152608490fd5b1561362e57565b60405162461bcd60e51b815260206004820152602f60248201527f53776170583a206e6f7420737570706f7274206665652d6f6e2d7472616e736660448201526e657220746f6b656e20666f7220563360881b6064820152608490fd5b1561369257565b60405162461bcd60e51b815260206004820152601960248201527f53776170583a20746f6f206d75636820726571756573746564000000000000006044820152606490fd5b92613795949161376d93946136ea6151a2565b6136f26151a2565b6136fb33614736565b6137036151a2565b61370b6151a2565b6001606c556137186151a2565b6137206151a2565b609e805460ff19169055600580546001600160a01b03199081166001600160a01b039384161790915560068054821693831693909317909255600380549092169216919091179055600155565b613778612710600255565b60018060a01b03166001600160601b0360a01b6004541617600455565b5f195f55565b6020906137a66139e1565b6137ae613a01565b6137be6060820151421115612839565b60a08101906137cf8251151561357f565b6138256132a63415159283613861575b6080810151604082015161380f91906001600160a01b03168351916138026102d7565b928352338a840152614a27565b505f5495015185906001600160a01b0316613ae0565b613834575b505f195f55612337565b6138429061152c83346129a1565b801561382a575f80808061385b94335af16109c46129ae565b5f61382a565b61386e85513410156135cb565b6137df565b1561035e57565b60208183031261035e578035906001600160401b03821161035e57019060408282031261035e5760405191604083018381106001600160401b0382111761024e5760405280356001600160401b03811161035e576020926138dc9183016103f1565b835201356138e98161040f565b602082015290565b9161391961393f919492945f8513938480156139d8575b61391190613873565b81019061387a565b936139248551613a1c565b600654929591949192859087906001600160a01b0316614daf565b50156139c257506001600160a01b03818116908316105b156139795750602092909201516102d592906001600160a01b03165b33916142dd565b90506139888351516042111590565b156139a95750906139a69161399d82516148de565b82523390614a27565b50565b61397260206102d594845f55015160018060a01b031690565b92506001600160a01b0382811690821610613956565b505f8713613908565b6002606c54146139f2576002606c55565b633ee5aeb560e01b5f5260045ffd5b60ff609e5416613a0d57565b63d93c066560e01b5f5260045ffd5b90613a2b601483511015614dd3565b602082015160601c916017815110613a6057601781015190602b81613a57601792602094511015614dd3565b01015160601c91565b60405162461bcd60e51b8152602060048201526014602482015273746f55696e7432345f6f75744f66426f756e647360601b6044820152606490fd5b15613aa357565b60405162461bcd60e51b815260206004820152601560248201527429bbb0b82c1d103a30b5b2903332b29032b93937b960591b6044820152606490fd5b335f9081526007602052604090205490919060ff16613bd357613b09613b129160015490614e97565b60025490614ed3565b906001600160a01b031680158015613bb6575b80613bad575b15613b8f57613b595f80808086613b4960035460018060a01b031690565b5af1613b536129ae565b50613a9c565b604080518381524260208201523392917f205442d60b70af1203d43cab62352c3b69b94f091be32fe683198057282b5c9291a390565b600354613ba89083906001600160a01b03163384614ef7565b613b59565b50814711613b2b565b50600454613bcc906001600160a01b03166107e3565b8114613b25565b50505f90565b602081526040613bf483518260208501526060840190612d7f565b6020909301516001600160a01b031691015290565b919082604091031261035e576020825192015190565b6001600160a01b039182168152911515602083015260408201929092529116606082015260a06080820181905261040c92910190612d7f565b600160ff1b811461298d575f0390565b613cad92916040916001600160a01b03821615613d86575b6107e35f613cb3613c918751613a1c565b6001600160a01b03808316908416109a8b969093909290612b72565b93614f3b565b93828214613d6257613d04613cda613ce86401000276a4995b895192839160208301613bd9565b03601f1981018352826102a4565b8751630251596160e31b81529889978896879560048701613c1f565b03925af190811561093b5761040c925f915f93613d2f575b5015613d285750613c58565b9050613c58565b909250613d54915060403d604011613d5b575b613d4c81836102a4565b810190613c09565b915f613d1c565b503d613d42565b613d04613cda613ce873fffd8963efd1fc6a506488495d951d5263988d2599613ccc565b309150613c80565b613dd793926040929091906001600160a01b03811615613e49575b5f6107e391613ddd613dbb8851613a1c565b6001600160a01b03808316908416109b8c979093909290612b72565b94614f3b565b946001600160a01b038116158314613e395750828214613e1657613d04613cda613ce86401000276a45b99895192839160208301613bd9565b613d04613cda613ce873fffd8963efd1fc6a506488495d951d5263988d25613e07565b613cda613ce8613d049299613ccc565b5030613da9565b91613e5a91614f4a565b6001600160a01b038316735c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f03613f24576040516001600160601b0319606093841b8116602083019081529290931b9092166034830152613cda91613f1b9190613eb8816048810186565b5190206040516001600160f81b03196020820190815260609590951b6001600160601b031916602182015260358101919091527f96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f60558201529182906075820190565b519020805f5290565b6040516001600160601b0319606093841b8116602083019081529290931b9092166034830152613cda91613f1b9190613f5e816048810186565b5190206040516001600160f81b03196020820190815260609590951b6001600160601b031916602182015260358101919091527fe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c630360558201529182906075820190565b15613fc857565b60405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a20494e56414c49445f5041544800006044820152606490fd5b90614017826102f6565b61402460405191826102a4565b8281528092614035601f19916102f6565b0190602036910137565b909291614050600282511015613fc1565b61405a815161400d565b93845115612a4a5760208501525f5b81515f19810190811161298d578110156140d357806140c06140af6140936122cf60019587612a5f565b6140a86122cf6140a286612f33565b88612a5f565b9087615019565b906140ba848a612a5f565b51614647565b6140cc6140a283612f33565b5201614069565b505050565b9092915f5b6140e7835161297f565b8110156142b4576140fb6122cf8285612a5f565b9061410b6122cf61125483612f33565b916141168382614f4a565b506141286107e36107e3868589613e50565b9060405192630240bc6b60e21b8452606084600481865afa93841561093b575f905f95614286575b506001600160a01b03918216929091168214936001600160701b0390811691168415614280575b6040516370a0823160e01b81526001600160a01b038516600482015292602090849060249082905afa801561093b5781610cbd916141bb955f9161426857506142bb565b9115614261575f91935b6141cf8751612992565b841015614259576141f6906141ef6122cf6141e987612f41565b8a612a5f565b9087613e50565b905b614200612d64565b94813b1561035e575f809461422b6040519889968795869463022c0d9f60e01b865260048601612da3565b03925af191821561093b57600192614245575b50016140dd565b8061092f5f614253936102a4565b5f61423e565b5087906141f8565b5f936141c5565b610dfa915060203d8111610a9e57610a8f81836102a4565b90614177565b6001600160701b0395508591506142aa9060603d8111610ea557610e9381836102a4565b5095909150614150565b5050509050565b90810390811161298d5790565b9081602091031261035e575161040c816117ad565b60045490939291906142f7906001600160a01b03166107e3565b6001600160a01b039094169384148061441c575b156143f957506004549192509061432c906107e3906001600160a01b031681565b803b1561035e575f8391600460405180968193630d0e30db60e41b83525af191821561093b576143ac936020936143e5575b50600454614376906107e3906001600160a01b031681565b60405163a9059cbb60e01b81526001600160a01b03909216600483015260248201929092529283919082905f9082906044820190565b03925af1801561093b576143bd5750565b6139a69060203d6020116143de575b6143d681836102a4565b8101906142c8565b503d6143cc565b8061092f5f6143f3936102a4565b5f61435e565b6001600160a01b038116300361441357506102d59261458e565b6102d593614ef7565b508247101561430b565b9162ffffff915f6040805161443a81610289565b8281526020810183905201526001600160a01b0381811690851611614483575b6040519361446785610289565b6001600160a01b03908116855216602084015216604082015290565b9261445a565b815160208301519192916001600160a01b03808216908316101561035e57613cda92613f1b926001600160a01b0390811692614504916144d2916040911693015162ffffff1690565b604080516001600160a01b0395861660208201908152959094169084015262ffffff1660608301528160808101613cda565b5190206040516001600160f81b03196020820190815260609590951b6001600160601b031916602182015260358101919091527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460558201529182906075820190565b603a546001600160a01b0316330361457b57565b63118cdaa760e01b5f523360045260245ffd5b60405163a9059cbb60e01b60208201526001600160a01b03909216602483015260448201929092526102d5916145c7826064810161273e565b6150ba565b156145d357565b60405162461bcd60e51b815260206004820152602860248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4c604482015267495155494449545960c01b6064820152608490fd5b8115614633570490565b634e487b7160e01b5f52601260045260245ffd5b91909180156146dd5761467861467161467e92851515806146d4575b61466c906145cc565b614e17565b9283614e97565b92614e75565b9081019081811161298d5781106146985761040c91614629565b60405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b6044820152606490fd5b50841515614663565b60405162461bcd60e51b815260206004820152602b60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4960448201526a1394155517d05353d5539560aa1b6064820152608490fd5b603a80546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b9081156147e4576147a482826147a9931515806147db575b61479f906145cc565b614e97565b614e75565b90820391821161298d576147c6916147c090614e17565b90614629565b600181019081811161298d5781106146985790565b50851515614796565b60405162461bcd60e51b815260206004820152602c60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4f60448201526b155514155517d05353d5539560a21b6064820152608490fd5b602b906148558261484e81612f4f565b1015615125565b61485f825f612f5d565b5061486a6001615125565b6148808151614879845f612f5d565b1115615162565b816148975750506040515f81526020810160405290565b60405191601f811691821560051b808486010193838501920101905b8084106148cb5750508252601f01601f191660405290565b90926020809185518152019301906148b3565b8051601619810181811161298d576148f98161484e81612f4f565b614908601761484e8382612f5d565b6149188351614879836017612f5d565b80614930575050506040515f81526020810160405290565b604051926017601f8316801560051b908181880101956016199087010193010101905b80841061496b5750508252601f01601f191660405290565b9092602080918551815201930190614953565b92919092614990600283511015613fc1565b61499a825161400d565b9384515f19810190811161298d576149b29086612a5f565b5281515f19810190811161298d57805b6149cb57505050565b614a0b6149fa6149e66122cf6149e08561297f565b87612a5f565b6149f36122cf8588612a5f565b9085615019565b90614a058489612a5f565b5161477e565b614a176149e08361297f565b52801561298d575f1901806149c2565b919291906001600160a01b03811615614b47575b60406107e391614a66614a4e8751613a1c565b6001600160a01b038084169083161096929091612b72565b835f614a79614a7488614f3b565b613c58565b93828214614b2357614abb613cda614a9f6401000276a49c895192839160208301613bd9565b8751630251596160e31b81529b8c978896879560048701613c1f565b03925af190811561093b575f945f92614aff575b5015614aeb5790614ae26102d592613c58565b935b9314613873565b9290614af96102d592613c58565b93614ae4565b909450614b1b915060403d604011613d5b57613d4c81836102a4565b90935f614acf565b614abb613cda614a9f73fffd8963efd1fc6a506488495d951d5263988d259c613ccc565b5030614a3b565b91939291906001600160a01b03811615614c7c575b60406107e391614b76614a4e8651613a1c565b835f614b84614a7488614f3b565b6001600160a01b038b16159a909490828c14614c6c5750828214614c4957614bdd613cda614bc16401000276a45b9b895192839160208301613bd9565b8751630251596160e31b81529a8b978896879560048701613c1f565b03925af190811561093b575f935f92614c25575b5015614c1557614c0090613c58565b915b93614c0b575050565b6102d59114613873565b91614c1f90613c58565b91614c02565b909350614c41915060403d604011613d5b57613d4c81836102a4565b90925f614bf1565b614bdd613cda614bc173fffd8963efd1fc6a506488495d951d5263988d25614bb2565b613cda614bc1614bdd929b613ccc565b5030614b63565b919392905f5b614c93825161297f565b811015614da757614ca76122cf8284612a5f565b90614cbd6122cf614cb783612f33565b85612a5f565b91614cc88382614f4a565b5090614cd66140a284612f33565b51916001600160a01b03828116911603614d9757614d2f6107e36107e35f94965b614d018951612992565b871015614d9057614d27614d206122cf614d1a8a612f41565b8c612a5f565b828c613e50565b945b8a613e50565b614d37612d64565b94813b1561035e575f8094614d626040519889968795869463022c0d9f60e01b865260048601612da3565b03925af191821561093b57600192614d7c575b5001614c89565b8061092f5f614d8a936102a4565b5f614d75565b8c94614d29565b614d2f6107e36107e35f96614cf7565b505050509050565b6001600160a01b0393614dc8939192612b909290614426565b1680330361035e5790565b15614dda57565b60405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b6044820152606490fd5b906103e58202918083046103e5148115171561298d576103e5830403614e3957565b60405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b6044820152606490fd5b906103e88202918083046103e8148115171561298d576103e8830403614e3957565b5f92918015918215614ead575b505015614e3957565b8082029450915081158285048214171561298d57614ecb9084614629565b145f80614ea4565b908015614ee35761040c91614629565b634e487b7160e01b5f52600160045260245ffd5b6040516323b872dd60e01b60208201526001600160a01b0392831660248201529290911660448301526064808301939093529181526102d5916145c76084836102a4565b600160ff1b81101561035e5790565b9091906001600160a01b03808416908216808214614fc6571015614fc157915b906001600160a01b03831615614f7c57565b60405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a205a45524f5f4144445245535300006044820152606490fd5b614f6a565b60405162461bcd60e51b815260206004820152602560248201527f556e697377617056324c6962726172793a204944454e544943414c5f41444452604482015264455353455360d81b6064820152608490fd5b90606060049261503e61502c8685614f4a565b50956001600160a01b03928590613e50565b1660405193848092630240bc6b60e21b82525afa91821561093b575f905f9361508b575b506001600160701b03928316939216916001600160a01b039182169116036150875791565b9091565b6001600160701b0393508391506150b09060603d606011610ea557610e9381836102a4565b5093909150615062565b5f806150e29260018060a01b03169360208151910182865af16150db6129ae565b90836151cd565b805190811515918261510a575b50506150f85750565b635274afe760e01b5f5260045260245ffd5b61511d92506020809183010191016142c8565b155f806150ef565b1561512c57565b60405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606490fd5b1561516957565b60405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606490fd5b60ff5f8051602061522c8339815191525460401c16156151be57565b631afcd79f60e31b5f5260045ffd5b906151f157508051156151e257805190602001fd5b630a12f52160e11b5f5260045ffd5b81511580615222575b615202575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b156151fa56fef0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0ea264697066735822122028da49c44c096942378115c02739e31f194dda1faaef8e389be874d6c214dea464736f6c634300081a0033

Deployed Bytecode

0x6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c8063130e594c146102195780631698ee8214610214578063180b0d7e1461020f5780631d5f45f51461020a5780633f4ba83a1461020557806345596e2e14610200578063472798df146101fb57806358e3ce30146101f65780635a4882d1146101f15780635b769f3c146101ec5780635b9e9006146101e75780635c975abb146101e257806366a5a99e146101dd57806368e0d4e1146101d8578063715018a6146101d35780638456cb59146101ce5780638d7f6c3a146101c95780638da5cb5b146101c45780639036f625146101bf578063936c044b146101ba578063978bbdb9146101b5578063a14bef8f146101b0578063a42dce80146101ab578063a7d14ad2146101a6578063ad5c4648146101a1578063bfc60df91461019c578063c415b95c14610197578063d5e4098314610192578063f2fde38b1461018d578063f7013ef614610188578063f83bda78146101835763fa461e330361000e57612070565b611fc5565b611e17565b611dc7565b611c6f565b611c47565b611c07565b611bdf565b61199d565b61194d565b611838565b61181b565b6117b7565b611713565b6116eb565b611406565b6113ad565b611352565b61132a565b611090565b610fb8565b610b2f565b610aa5565b6109ec565b6109d0565b610751565b610664565b6105fe565b6105d6565b6105b9565b610558565b61042b565b634e487b7160e01b5f52604160045260245ffd5b61010081019081106001600160401b0382111761024e57604052565b61021e565b60a081019081106001600160401b0382111761024e57604052565b60c081019081106001600160401b0382111761024e57604052565b606081019081106001600160401b0382111761024e57604052565b90601f801991011681019081106001600160401b0382111761024e57604052565b604051906102d5610120836102a4565b565b604051906102d56040836102a4565b604051906102d5610140836102a4565b6001600160401b03811161024e5760051b60200190565b6001600160401b03811161024e57601f01601f191660200190565b9291926103348261030d565b9161034260405193846102a4565b82948184528183011161035e578281602093845f960137010152565b5f80fd5b81601f8201121561035e57803590610379826102f6565b9261038760405194856102a4565b82845260208085019360051b8301019181831161035e5760208101935b8385106103b357505050505090565b84356001600160401b03811161035e57820183603f8201121561035e576020916103e68583604086809601359101610328565b8152019401936103a4565b9080601f8301121561035e5781602061040c93359101610328565b90565b6001600160a01b0381160361035e57565b35906102d58261040f565b602036600319011261035e576004356001600160401b03811161035e57610120600319823603011261035e5761045f6102c5565b9080600401356001600160401b03811161035e576104839060043691840101610362565b825260248101356001600160401b03811161035e576104a890600436918401016103f1565b60208301526104b960448201610420565b60408301526064810135916001600160401b03831161035e57610104610534926104ec61054495600436918401016103f1565b60608401526104fd60848201610420565b608084015261050e60a48201610420565b60a084015260c481013560c084015260e481013560e084015201356101008201526120d0565b6040519081529081906020820190565b0390f35b359062ffffff8216820361035e57565b3461035e57606036600319011261035e576004356105758161040f565b602435906105828261040f565b60443562ffffff8116810361035e5760209261059d92612b72565b6040516001600160a01b039091168152f35b5f91031261035e57565b3461035e575f36600319011261035e576020600254604051908152f35b3461035e575f36600319011261035e576006546040516001600160a01b039091168152602090f35b3461035e575f36600319011261035e57610616614567565b609e5460ff8116156106555760ff1916609e557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b638dfc202b60e01b5f5260045ffd5b3461035e57602036600319011261035e57600435610680614567565b61271081101561068f57600155005b60405162461bcd60e51b815260206004820152601860248201527f72617465206f7665722066656544656e6f6d696e61746f7200000000000000006044820152606490fd5b61010090600319011261035e57604051906106ee82610232565b816106f96004610420565b81526107056024610420565b60208201526107146044610548565b60408201526107236064610420565b6060820152608435608082015260a43560a082015260c43560c082015260e061074c60e4610420565b910152565b61010036600319011261035e57610767366106d4565b61076f6139e1565b610777613a01565b6107876080820151421115612839565b60a08101610797815115156128c7565b81516001600160a01b03161561097f575b81516107ca906107c3906001600160a01b0316835190613ae0565b82516129a1565b81526020820180515f91906107ef906001600160a01b03165b6001600160a01b031690565b15610953575b61087b919251835f14610940575f5b60e08601516001600160a01b03168651909290610865906001600160a01b031661085761084861083a60408c015162ffffff1690565b97516001600160a01b031690565b60405197889360208501612ab3565b03601f1981018652856102a4565b61086d6102d7565b938452336020850152613d8e565b9061088c60c0840151831015612b9a565b61089f575b610544906105346001606c55565b6004546108b6906107e3906001600160a01b031681565b803b1561035e57604051632e1a7d4d60e01b815260048101839052905f908290602490829084905af1801561093b575f80808561090c60606105449961091c988598610921575b5001516001600160a01b031690565b5af16109166129ae565b50612be6565b610891565b8061092f87610935936102a4565b806105af565b5f6108fd565b612b1b565b60608501516001600160a01b0316610804565b60045461087b9250610976906001600160a01b03165b6001600160a01b03168252565b600191506107f5565b6004546001600160a01b0316825261099a8151341015612913565b6109a58151346129a1565b806109b1575b506107a8565b5f8080806109ca94335af16109c46129ae565b506129dd565b5f6109ab565b3461035e575f36600319011261035e5760205f54604051908152f35b3461035e57604036600319011261035e57600435610a098161040f565b60243590610a168261040f565b610a1e614567565b610a326001600160a01b0383161515612c32565b6040516370a0823160e01b8152306004820152916001600160a01b039190911690602083602481855afa91821561093b57610018935f93610a74575b5061458e565b610a9791935060203d602011610a9e575b610a8f81836102a4565b810190612b0c565b915f610a6e565b503d610a85565b3461035e57602036600319011261035e57600435610ac28161040f565b610aca614567565b6001600160a01b0316610ade811515612c32565b6001600160601b0360a01b60045416176004555f80f35b60a090600319011261035e57600435610b0d8161040f565b90602435610b1a8161040f565b90604435906064359060843561040c8161040f565b610b3836610af5565b610b439391936139e1565b610b4b613a01565b6001600160a01b038116928590610b63851515612c6d565b610b6e811515612cb9565b5f916001600160a01b031615610f63575b80610b8d610b939289613ae0565b906129a1565b9015610f5357610ba49130876142dd565b6001600160a01b0316905f908215610f4a575b8115610efa57600454610bd4906107e3906001600160a01b031681565b6040516370a0823160e01b815230600482015290602090829060249082905afa90811561093b575f91610edb575b50945b604051630dfe168160e01b8152602081600481865afa90811561093b575f91610eac575b50604051630240bc6b60e21b815291606083600481875afa92831561093b575f905f94610e6d575b506001600160a01b03918216929091168214926001600160701b0390811691168315610e67575b6040516370a0823160e01b81526001600160a01b038616600482015292602090849060249082905afa801561093b5781610cbd91610cc2955f91610de1575b506142bb565b614647565b9015610e60575f90915b8315610e595730905b610cdd612d64565b93813b1561035e575f8094610d086040519788968795869463022c0d9f60e01b865260048601612da3565b03925af1801561093b57610e45575b5015610e005750600454610d35906107e3906001600160a01b031681565b6040516370a0823160e01b81523060048201529092602082602481875afa801561093b57610d69925f91610de157506142bb565b90823b1561035e57604051632e1a7d4d60e01b815260048101839052925f908490602490829084905af190811561093b5761054493610dc392610dcd575b50610dbb5f80808087335af16109166129ae565b821015612dce565b6105346001606c55565b8061092f5f610ddb936102a4565b5f610da7565b610dfa915060203d602011610a9e57610a8f81836102a4565b5f610cb7565b6040516370a0823160e01b815233600482015290602090829060249082905afa90811561093b5761054493610dc392610e3f925f91610de157506142bb565b91610dbb565b8061092f5f610e53936102a4565b5f610d17565b3390610cd5565b5f91610ccc565b90610c78565b6001600160701b039450849150610e9b9060603d606011610ea5575b610e9381836102a4565b810190612d2e565b5094909150610c51565b503d610e89565b610ece915060203d602011610ed4575b610ec681836102a4565b810190612d05565b5f610c29565b503d610ebc565b610ef4915060203d602011610a9e57610a8f81836102a4565b5f610c02565b6040516370a0823160e01b8152336004820152602081602481875afa90811561093b575f91610f2b575b5094610c05565b610f44915060203d602011610a9e57610a8f81836102a4565b5f610f24565b60019150610bb7565b610f5e9133876142dd565b610ba4565b809650610f739150341015612913565b600454600190610b93906001600160a01b031696610f9181346129a1565b80610f9f575b509050610b7f565b5f808080610fb294335af16109c46129ae565b5f610f97565b3461035e575f36600319011261035e57602060ff609e54166040519015158152f35b60e060031982011261035e57600435610ff28161040f565b9160243591604435916064356001600160401b03811161035e578260238201121561035e578060040135926001600160401b03841161035e5760248460051b8301011161035e5760240191906110486084610420565b9060a4359061040c60c4610420565b60206040818301928281528451809452019201905f5b81811061107a5750505090565b825184526020938401939092019160010161106d565b61110e6110c96111646111526110a536610fda565b9895929a94979399906110b99792976139e1565b6110c1613a01565b421115612839565b898982936110d8811515612cb9565b5f936001600160a01b0316156112c6575b906111196110fe83610b8d6111209589613ae0565b978461111361110e8b9786612e24565b612e4c565b93612e2d565b908b613e50565b91156112b6576111319130846142dd565b6111416107e361110e8b8b612e24565b6001600160a01b0390911614612e56565b61115d368888612e91565b908561403f565b936111816107e36107e361110e61117a8a61297f565b8a86612e3c565b6040516370a0823160e01b81526001600160a01b03841660048201529290602090849060249082905afa91821561093b576112239588945f94611278575b506107e361110e6111f6936111e66107e394876111e160209a9b369086612e91565b6140d8565b8b6111f08161297f565b91612e3c565b6040516370a0823160e01b81526001600160a01b0390921660048301529094859190829081906024820190565b03915afa94851561093b5761125a61124c6112549361054498611262975f91610de157506142bb565b92839261297f565b86612a5f565b521015612dce565b61126c6001606c55565b60405191829182611057565b6020945061110e6111f6936111e66107e394876111e16112a76107e3978c3d8e11610a9e57610a8f81836102a4565b9a5050509450509350506111bf565b6112c19133846142dd565b611131565b93505050506112d781341015612913565b6001896111208a6111196110fe6112f560045460018060a01b031690565b9661130081346129a1565b80611311575b5092935050506110e9565b5f80808061132494335af16109c46129ae565b5f611306565b3461035e575f36600319011261035e576005546040516001600160a01b039091168152602090f35b3461035e575f36600319011261035e5761136a614567565b603a80546001600160a01b031981169091555f906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b3461035e575f36600319011261035e576113c5614567565b6113cd613a01565b600160ff19609e541617609e557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1005b61140f36610af5565b61141d9491949392936139e1565b611425613a01565b90926001600160a01b03821691908461143f841515612c6d565b61144a821515612ee7565b5f906001600160a01b0316156116c9575b5f946001600160a01b0316156116c0575b604051630dfe168160e01b815292602084600481885afa93841561093b575f9461169f575b50604051630240bc6b60e21b815293606085600481895afa94851561093b575f905f9661166b575b506001600160a01b03898116921691909114946114ea916001600160701b0391821691168615611665575b8a61477e565b96879261150c6114fa8584613ae0565b956115058787612f5d565b1115612f6a565b15611654579161152291611531949330906142dd565b61152c86346129a1565b6129a1565b8061163b575b505b15611633575f84915b831561162c5730905b611553612d64565b93813b1561035e575f809461157e6040519788968795869463022c0d9f60e01b865260048601612da3565b03925af1801561093b57611618575b506115a057610544906105346001606c55565b6004546115b7906107e3906001600160a01b031681565b803b1561035e57604051632e1a7d4d60e01b815260048101849052905f908290602490829084905af1801561093b575f80806105449661091c958295611604575b50335af16109166129ae565b8061092f84611612936102a4565b5f6115f8565b8061092f5f611626936102a4565b5f61158d565b339061154b565b835f91611542565b5f80808061164e94335af16109c46129ae565b5f611537565b611660935033906142dd565b611539565b906114e4565b6001600160701b0396506114ea929150611694879160603d606011610ea557610e9381836102a4565b5097509192506114b9565b6116b991945060203d602011610ed457610ec681836102a4565b925f611491565b6001945061146c565b506004546001600160a01b0316945060016116e634831115612913565b61145b565b3461035e575f36600319011261035e57603a546040516001600160a01b039091168152602090f35b602036600319011261035e576004356001600160401b03811161035e5760a0600319823603011261035e576040519061174b82610253565b8060040135916001600160401b03831161035e5760846105349261177861054495600436918401016103f1565b835260248101356117888161040f565b6020840152604481013560408401526064810135606084015201356080820152612fb6565b8015150361035e57565b3461035e57604036600319011261035e576004356117d48161040f565b602435906117e1826117ad565b6117e9614567565b6001600160a01b03166117fd811515612c32565b5f52600760205260405f209060ff8019835416911515161790555f80f35b3461035e575f36600319011261035e576020600154604051908152f35b602036600319011261035e576004356001600160401b03811161035e57610140600319823603011261035e5761186c6102e6565b9080600401356001600160401b03811161035e576118909060043691840101610362565b825260248101356001600160401b03811161035e576118b590600436918401016103f1565b60208301526118c660448201610420565b60408301526064810135916001600160401b03831161035e57610124610534926118f961054495600436918401016103f1565b606084015261190a60848201610420565b608084015260a481013560a084015261192560c48201610420565b60c084015260e481013560e084015261010481013561010084015201356101208201526130d0565b3461035e57602036600319011261035e5760043561196a8161040f565b611972614567565b6001600160a01b0316611986811515612c32565b6001600160601b0360a01b60035416176003555f80f35b61010036600319011261035e576119b3366106d4565b6119bb6139e1565b6119c3613a01565b6119d36080820151421115612839565b60c08101906119e48251151561357f565b80515f91906001600160a01b031615611bb4575b60208101805190935f91611a14906001600160a01b03166107e3565b15611b9d575b611a9060a0840195865190845f14611b8a575f5b60e0870151611a4f906001600160a01b03165b92516001600160a01b031690565b92611a7a611a6360408a015162ffffff1690565b8951909590610857906001600160a01b0316610848565b611a826102d7565b938452336020850152614b4e565b93611ac1611aad86611aa8875160018060a01b031690565b613ae0565b92611ab88488612f5d565b9051101561368b565b611b5d575b50611ad9575b5f195f5561054482610dc3565b600454611af0906107e3906001600160a01b031681565b92805193803b1561035e57604051632e1a7d4d60e01b815260048101959095525f908590602490829084905af193841561093b575f808093611b4a6060611b579784966105449b610921575001516001600160a01b031690565b9051905af16109166129ae565b5f611acc565b611b6b9061152c85346129a1565b8015611ac6575f808080611b8494335af16109c46129ae565b5f611ac6565b60608601516001600160a01b0316611a2e565b6004546001600160a01b0316855260019150611a1a565b60045460019250611bcd906001600160a01b0316610969565b611bda83513410156135cb565b6119f8565b3461035e575f36600319011261035e576004546040516001600160a01b039091168152602090f35b3461035e57602036600319011261035e57600435611c248161040f565b60018060a01b03165f526007602052602060ff60405f2054166040519015158152f35b3461035e575f36600319011261035e576003546040516001600160a01b039091168152602090f35b610544611c9a611262611d5e611cf1611c8736610fda565b9896919793959a906110b99593956139e1565b8091611ca78b151561357f565b5f916001600160a01b031615611d99575b611cd1611cf791611cca36888a612e91565b908b61497e565b9a6115058c611ce9611ce282612a3d565b5187613ae0565b968791612a3d565b51612f5d565b611d1b611d0761110e8688612e24565b611d1461110e8789612e2d565b908a613e50565b9015611d7d57611d4f9291611d3c91611d338c612a3d565b519130906142dd565b61152c611d488a612a3d565b51346129a1565b80611d64575b505b3691612e91565b84614c83565b5f808080611d7794335af16109c46129ae565b5f611d55565b611d949250611d8b8a612a3d565b519133906142dd565b611d57565b6004546001600160a01b0316925060019150611cf790611cd190611dbf348e1115612913565b915050611cb8565b3461035e57602036600319011261035e57600435611de48161040f565b611dec614567565b6001600160a01b03811615611e045761001890614736565b631e4fbdf760e01b5f525f60045260245ffd5b3461035e5760a036600319011261035e57600435611e348161040f565b60243590611e418261040f565b604435611e4d8161040f565b606435611e598161040f565b608435915f8051602061522c8339815191525494611e92611e85611e818860ff9060401c1690565b1590565b966001600160401b031690565b8680611fb2575b159081611f8b575b50611f7d57611ee49486611edb60016001600160401b03195f8051602061522c8339815191525416175f8051602061522c83398151915255565b611f43576136d7565b611eea57005b611f1460ff60401b195f8051602061522c83398151915254165f8051602061522c83398151915255565b604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1005b611f786801000000000000000060ff60401b195f8051602061522c8339815191525416175f8051602061522c83398151915255565b6136d7565b62dc149f60e41b5f5260045ffd5b303b15915081611f9e575b50155f611ea1565b600191506001600160401b0316145f611f96565b5060016001600160401b03821610611e99565b602036600319011261035e576004356001600160401b03811161035e5760c0600319823603011261035e5760405190611ffd8261026e565b8060040135916001600160401b03831161035e5760a46105349261202a61054495600436918401016103f1565b8352602481013561203a8161040f565b602084015261204b60448201610420565b60408401526064810135606084015260848101356080840152013560a082015261379b565b3461035e57606036600319011261035e576044356024356004356001600160401b03831161035e573660238401121561035e578260040135916001600160401b03831161035e57366024848601011161035e5760246100189401916138f1565b6120d86139e1565b6120e0613a01565b6120f060c0820151421115612839565b5f6120ff60028351511461287b565b60e0820161210f815115156128c7565b61211c6020840151613a1c565b919390925f9290916001600160a01b038616156127e7575b612149612142845188613ae0565b84516129a1565b83526121756121588851612a3d565b51612161612a73565b906020815191012090602081519101201490565b806127d4575b15612396575050926122739360408601926121a685846121a1875160018060a01b031690565b613e50565b9015612384576121b991519030846142dd565b6121dd6121c4612aea565b916121ce83612a3d565b6001600160a01b039091169052565b6121ea836121ce83612a4f565b6121f76060860151613a1c565b50939050612203612aea565b91612211826121ce85612a3d565b61221e856121ce85612a4f565b608087018051909261223b918791906001600160a01b0316613e50565b60a0880180516040516370a0823160e01b81526001600160a01b03918216600482015298971696909590602090899081906024820190565b03818a5afa97881561093b575f98612342575b50936122dc936122b1602097946122cf946122ab6123089b995160018060a01b031690565b916140d8565b83516122ab906001600160a01b03165b91516001600160a01b031690565b516001600160a01b031690565b6040516370a0823160e01b81526001600160a01b03909116600482015292839190829081906024820190565b03915afa90811561093b57612337926101009261232b925f91610de157506142bb565b925b0151821015612b26565b906102d56001606c55565b6123089795919850936122b1602097946122cf946122ab6123726122dc998c3d8e11610a9e57610a8f81836102a4565b9c95999b505094509497505093612286565b61239191519033846142dd565b6121b9565b6123a7612158889694959651612a3d565b806127c1575b1561256f57505061242461247f9461240894936124116124349460408a01966123e182866121a18b5160018060a01b031690565b901561255d5783516123f49130876142dd565b6123fc612aea565b9788946121ce86612a3d565b6121ce84612a4f565b84516001600160a01b031690519061403f565b61242e815161297f565b90612a5f565b51606085016124438151613a1c565b5060a0880180516040516370a0823160e01b81526001600160a01b03918216600482015298921696909590925090602090889081906024820190565b0381895afa96871561093b575f9761251d575b506124f495936122dc936124be602097946124b66124e6955160018060a01b031690565b9030906140d8565b83516001600160a01b03169051916124d46102d7565b9283523088840152613c68565b613c68565b50516001600160a01b031690565b03915afa90811561093b576123379261010092612517925f91610de157506142bb565b9261232d565b6124e6919750936122dc936124be602097946124b661254c6124f49b998b3d8d11610a9e57610a8f81836102a4565b9b9550509497505093509395612492565b835161256a9133876142dd565b6123f4565b90949192935061258b6125828751612a3d565b51612161612a93565b806127ae575b156126e75750612643612424608061261261267d97612626976121a1976125fc8c986125ee6125dc6125c660608d0151613a1c565b509c90809a8e92019e8f5160018060a01b031690565b94519360405196879360208501612ab3565b03601f1981018552846102a4565b6126046102d7565b928352336020840152613c68565b61261a612aea565b9687926121ce84612a3d565b612633856121ce84612a4f565b85516001600160a01b031661403f565b5060a0850180516040516370a0823160e01b81526001600160a01b0391821660048201529592169390929091602090869081906024820190565b0381875afa94851561093b575f956126b3575b50826122cf6124f495936122dc936122ab6122c16020985160018060a01b031690565b6122dc919550926122cf6124f495936126da602096873d8911610a9e57610a8f81836102a4565b9793509395505092612690565b949391906126f86125828651612a3d565b8061279b575b612713575b505050506101006123379161232d565b61233794955061279292849261274c6127649361273e61010098519360405195869360208501612ab3565b03601f1981018452836102a4565b6127546102d7565b9182523360208301523090613c68565b9081905260a08501516001600160a01b03166060860151916127846102d7565b928352306020840152613c68565b92915f80612703565b506127a96125828651612a4f565b6126fe565b506127bc6121588751612a4f565b612591565b506127cf6125828851612a4f565b6123ad565b506127e26121588851612a4f565b61217b565b945091506127f88151341015612913565b600454600192906001600160a01b0316946128148351346129a1565b80612820575b50612134565b5f80808061283394335af16109c46129ae565b5f61281a565b1561284057565b60405162461bcd60e51b8152602060048201526013602482015272151c985b9cd858dd1a5bdb881d1bdbc81bdb19606a1b6044820152606490fd5b1561288257565b60405162461bcd60e51b815260206004820152601e60248201527f53776170583a206f6e6c79203220726f7574657320737570706f7274656400006044820152606490fd5b156128ce57565b60405162461bcd60e51b815260206004820152601860248201527f53776170583a20616d6f756e7420696e206973207a65726f00000000000000006044820152606490fd5b1561291a57565b60405162461bcd60e51b815260206004820152602360248201527f53776170583a20616d6f756e7420696e20616e642076616c7565206d69736d616044820152620e8c6d60eb1b6064820152608490fd5b634e487b7160e01b5f52601160045260245ffd5b5f1981019190821161298d57565b61296b565b60011981019190821161298d57565b9190820391821161298d57565b3d156129d8573d906129bf8261030d565b916129cd60405193846102a4565b82523d5f602084013e565b606090565b156129e457565b60405162461bcd60e51b815260206004820152601760248201527f53776170583a20726566756e6420455448206572726f720000000000000000006044820152606490fd5b634e487b7160e01b5f52603260045260245ffd5b805115612a4a5760200190565b612a29565b805160011015612a4a5760400190565b8051821015612a4a5760209160051b010190565b60405190612a826040836102a4565b60028252613b1960f11b6020830152565b60405190612aa26040836102a4565b6002825261763360f01b6020830152565b606091821b6001600160601b0319908116825260e89390931b6001600160e81b031916601482015292901b166017820152602b0190565b60405160609190612afb83826102a4565b6002815291601f1901366020840137565b9081602091031261035e575190565b6040513d5f823e3d90fd5b15612b2d57565b60405162461bcd60e51b815260206004820152601a60248201527f53776170583a20746f6f206c6974746c652072656365697665640000000000006044820152606490fd5b6006546001600160a01b0393612b969391851692612b909290614426565b90614489565b1690565b15612ba157565b60405162461bcd60e51b815260206004820152601e60248201527f53776170583a20696e73756666696369656e74206f757420616d6f756e7400006044820152606490fd5b15612bed57565b60405162461bcd60e51b815260206004820152601960248201527f53776170583a2073656e6420455448206f7574206572726f72000000000000006044820152606490fd5b15612c3957565b60405162461bcd60e51b815260206004820152600c60248201526b34b73b30b634b21030b2323960a11b6044820152606490fd5b15612c7457565b60405162461bcd60e51b815260206004820152601b60248201527f53776170583a20696e76616c696420706f6f6c206164647265737300000000006044820152606490fd5b15612cc057565b60405162461bcd60e51b815260206004820152601760248201527f53776170583a20616d6f757420696e206973207a65726f0000000000000000006044820152606490fd5b9081602091031261035e575161040c8161040f565b51906001600160701b038216820361035e57565b9081606091031261035e57612d4281612d1a565b916040612d5160208401612d1a565b92015163ffffffff8116810361035e5790565b60405190612d736020836102a4565b5f808352366020840137565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b909260809261040c95948352602083015260018060a01b031660408201528160608201520190612d7f565b15612dd557565b60405162461bcd60e51b815260206004820152602160248201527f53776170583a20696e73756666696369656e74206f757470757420616d6f756e6044820152601d60fa1b6064820152608490fd5b9015612a4a5790565b9060011015612a4a5760200190565b9190811015612a4a5760051b0190565b3561040c8161040f565b15612e5d57565b60405162461bcd60e51b815260206004820152600c60248201526b0d2dcecc2d8d2c840e0c2e8d60a31b6044820152606490fd5b929190612e9d816102f6565b93612eab60405195866102a4565b602085838152019160051b810192831161035e57905b828210612ecd57505050565b602080918335612edc8161040f565b815201910190612ec1565b15612eee57565b60405162461bcd60e51b815260206004820152601b60248201527f53776170583a20616d6f757420696e206d6178206973207a65726f00000000006044820152606490fd5b906001820180921161298d57565b906002820180921161298d57565b90601f820180921161298d57565b9190820180921161298d57565b15612f7157565b60405162461bcd60e51b815260206004820152601d60248201527f53776170583a2065786365737369766520696e70757420616d6f756e740000006044820152606490fd5b612fbe6139e1565b612fc6613a01565b612fd66040820151421115612839565b60608101612fe6815115156128c7565b34613093575b6130066107c3612ffc8451613a1c565b5050835190613ae0565b8152335b61305061301a8451516042111590565b918351835f1461307f5730905b6124e1613034885161483e565b9361303d6102d7565b9485526001600160a01b03166020850152565b808352901561306c57503061306583516148de565b835261300a565b6123379150608090920151821015612b26565b60208601516001600160a01b031690613027565b6130a08151341015612913565b6130ab8151346129a1565b806130b7575b50612fec565b5f8080806130ca94335af16109c46129ae565b5f6130b1565b6130d86139e1565b6130e0613a01565b6130f060e0820151421115612839565b5f6101208201906131038251151561357f565b341515908161356d575b6020840161311b8151613a1c565b509092606087019061312d8251613a1c565b5094905061313e6121588a51612a3d565b8061355a575b156132ff5750505060408601805190939061316b90839083906001600160a01b0316613e50565b916080880193818186516131849060018060a01b031690565b9161318e92613e50565b94613197612aea565b91836131a284612a3d565b6001600160a01b0390911690526131b883612a4f565b6001600160a01b03909116905280516001600160a01b0316826101008c01516131e09261497e565b916131e9612aea565b93856131f486612a3d565b6001600160a01b03909116905261320a85612a4f565b6001600160a01b0391821690528851168461322485612a3d565b5161322e9261497e565b97856132398a612a3d565b51600454909d8e998a926001600160a01b03166001600160a01b0316600160a01b600190038516145f149c6132a69c611aa89a6132b19f61329298611a419860c09861329897613292946132ef576122cf9230906142dd565b92614c83565b01516001600160a01b031690565b92611ab88486612f5d565b6132c2575b50906102d56001606c55565b6132d09061152c83346129a1565b80156132b6575f8080806132e994335af16109c46129ae565b5f6132b6565b6132fa9233906142dd565b6122cf565b6133126121588a97969394959751612a3d565b80613547575b1561344757505050805161332b90613a1c565b50505060408601805190929061334d90859083906001600160a01b0316613e50565b92613356612aea565b948261336187612a3d565b6001600160a01b03909116905261337786612a4f565b6001600160a01b03909116905280516001600160a01b031660a08901908682516133a09261497e565b946133aa86612a3d565b51600454909a8b96909187906001600160a01b03166001600160a01b03166132b19a6132a69a611aa8986134349761340695939492936133fe936001600160a01b038e160361343c576122cf91308e6142dd565b913091614c83565b61010082015160c0909201516001600160a01b03169051916134266102d7565b928352306020840152614a27565b905114613627565b6132fa91338e6142dd565b9197939450915061345b6125828451612a3d565b80613534575b613476575b5050506132a6846132b192613ae0565b60c096506132b193509061352e826134926132a6959451613a1c565b5093613292611a4161351e6134da6134a8612aea565b946134b6876121ce88612a3d565b6134c3816121ce88612a4f565b60808b0180519097906001600160a01b0316613e50565b85519096906134fa9086906001600160a01b03166101008d01519061497e565b9661350488612a3d565b519151916135106102d7565b928352336020840152614a27565b9c8d98015160018060a01b031690565b92613466565b506135426121588451612a4f565b613461565b506135556125828a51612a4f565b613318565b506135686121588a51612a4f565b613144565b61357a83513410156135cb565b61310d565b1561358657565b60405162461bcd60e51b815260206004820152601c60248201527f53776170583a20616d6f756e7420696e206d6178206973207a65726f000000006044820152606490fd5b156135d257565b60405162461bcd60e51b815260206004820152602760248201527f53776170583a20616d6f756e7420696e206d617820616e642076616c7565206d6044820152660d2e6dac2e8c6d60cb1b6064820152608490fd5b1561362e57565b60405162461bcd60e51b815260206004820152602f60248201527f53776170583a206e6f7420737570706f7274206665652d6f6e2d7472616e736660448201526e657220746f6b656e20666f7220563360881b6064820152608490fd5b1561369257565b60405162461bcd60e51b815260206004820152601960248201527f53776170583a20746f6f206d75636820726571756573746564000000000000006044820152606490fd5b92613795949161376d93946136ea6151a2565b6136f26151a2565b6136fb33614736565b6137036151a2565b61370b6151a2565b6001606c556137186151a2565b6137206151a2565b609e805460ff19169055600580546001600160a01b03199081166001600160a01b039384161790915560068054821693831693909317909255600380549092169216919091179055600155565b613778612710600255565b60018060a01b03166001600160601b0360a01b6004541617600455565b5f195f55565b6020906137a66139e1565b6137ae613a01565b6137be6060820151421115612839565b60a08101906137cf8251151561357f565b6138256132a63415159283613861575b6080810151604082015161380f91906001600160a01b03168351916138026102d7565b928352338a840152614a27565b505f5495015185906001600160a01b0316613ae0565b613834575b505f195f55612337565b6138429061152c83346129a1565b801561382a575f80808061385b94335af16109c46129ae565b5f61382a565b61386e85513410156135cb565b6137df565b1561035e57565b60208183031261035e578035906001600160401b03821161035e57019060408282031261035e5760405191604083018381106001600160401b0382111761024e5760405280356001600160401b03811161035e576020926138dc9183016103f1565b835201356138e98161040f565b602082015290565b9161391961393f919492945f8513938480156139d8575b61391190613873565b81019061387a565b936139248551613a1c565b600654929591949192859087906001600160a01b0316614daf565b50156139c257506001600160a01b03818116908316105b156139795750602092909201516102d592906001600160a01b03165b33916142dd565b90506139888351516042111590565b156139a95750906139a69161399d82516148de565b82523390614a27565b50565b61397260206102d594845f55015160018060a01b031690565b92506001600160a01b0382811690821610613956565b505f8713613908565b6002606c54146139f2576002606c55565b633ee5aeb560e01b5f5260045ffd5b60ff609e5416613a0d57565b63d93c066560e01b5f5260045ffd5b90613a2b601483511015614dd3565b602082015160601c916017815110613a6057601781015190602b81613a57601792602094511015614dd3565b01015160601c91565b60405162461bcd60e51b8152602060048201526014602482015273746f55696e7432345f6f75744f66426f756e647360601b6044820152606490fd5b15613aa357565b60405162461bcd60e51b815260206004820152601560248201527429bbb0b82c1d103a30b5b2903332b29032b93937b960591b6044820152606490fd5b335f9081526007602052604090205490919060ff16613bd357613b09613b129160015490614e97565b60025490614ed3565b906001600160a01b031680158015613bb6575b80613bad575b15613b8f57613b595f80808086613b4960035460018060a01b031690565b5af1613b536129ae565b50613a9c565b604080518381524260208201523392917f205442d60b70af1203d43cab62352c3b69b94f091be32fe683198057282b5c9291a390565b600354613ba89083906001600160a01b03163384614ef7565b613b59565b50814711613b2b565b50600454613bcc906001600160a01b03166107e3565b8114613b25565b50505f90565b602081526040613bf483518260208501526060840190612d7f565b6020909301516001600160a01b031691015290565b919082604091031261035e576020825192015190565b6001600160a01b039182168152911515602083015260408201929092529116606082015260a06080820181905261040c92910190612d7f565b600160ff1b811461298d575f0390565b613cad92916040916001600160a01b03821615613d86575b6107e35f613cb3613c918751613a1c565b6001600160a01b03808316908416109a8b969093909290612b72565b93614f3b565b93828214613d6257613d04613cda613ce86401000276a4995b895192839160208301613bd9565b03601f1981018352826102a4565b8751630251596160e31b81529889978896879560048701613c1f565b03925af190811561093b5761040c925f915f93613d2f575b5015613d285750613c58565b9050613c58565b909250613d54915060403d604011613d5b575b613d4c81836102a4565b810190613c09565b915f613d1c565b503d613d42565b613d04613cda613ce873fffd8963efd1fc6a506488495d951d5263988d2599613ccc565b309150613c80565b613dd793926040929091906001600160a01b03811615613e49575b5f6107e391613ddd613dbb8851613a1c565b6001600160a01b03808316908416109b8c979093909290612b72565b94614f3b565b946001600160a01b038116158314613e395750828214613e1657613d04613cda613ce86401000276a45b99895192839160208301613bd9565b613d04613cda613ce873fffd8963efd1fc6a506488495d951d5263988d25613e07565b613cda613ce8613d049299613ccc565b5030613da9565b91613e5a91614f4a565b6001600160a01b038316735c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f03613f24576040516001600160601b0319606093841b8116602083019081529290931b9092166034830152613cda91613f1b9190613eb8816048810186565b5190206040516001600160f81b03196020820190815260609590951b6001600160601b031916602182015260358101919091527f96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f60558201529182906075820190565b519020805f5290565b6040516001600160601b0319606093841b8116602083019081529290931b9092166034830152613cda91613f1b9190613f5e816048810186565b5190206040516001600160f81b03196020820190815260609590951b6001600160601b031916602182015260358101919091527fe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c630360558201529182906075820190565b15613fc857565b60405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a20494e56414c49445f5041544800006044820152606490fd5b90614017826102f6565b61402460405191826102a4565b8281528092614035601f19916102f6565b0190602036910137565b909291614050600282511015613fc1565b61405a815161400d565b93845115612a4a5760208501525f5b81515f19810190811161298d578110156140d357806140c06140af6140936122cf60019587612a5f565b6140a86122cf6140a286612f33565b88612a5f565b9087615019565b906140ba848a612a5f565b51614647565b6140cc6140a283612f33565b5201614069565b505050565b9092915f5b6140e7835161297f565b8110156142b4576140fb6122cf8285612a5f565b9061410b6122cf61125483612f33565b916141168382614f4a565b506141286107e36107e3868589613e50565b9060405192630240bc6b60e21b8452606084600481865afa93841561093b575f905f95614286575b506001600160a01b03918216929091168214936001600160701b0390811691168415614280575b6040516370a0823160e01b81526001600160a01b038516600482015292602090849060249082905afa801561093b5781610cbd916141bb955f9161426857506142bb565b9115614261575f91935b6141cf8751612992565b841015614259576141f6906141ef6122cf6141e987612f41565b8a612a5f565b9087613e50565b905b614200612d64565b94813b1561035e575f809461422b6040519889968795869463022c0d9f60e01b865260048601612da3565b03925af191821561093b57600192614245575b50016140dd565b8061092f5f614253936102a4565b5f61423e565b5087906141f8565b5f936141c5565b610dfa915060203d8111610a9e57610a8f81836102a4565b90614177565b6001600160701b0395508591506142aa9060603d8111610ea557610e9381836102a4565b5095909150614150565b5050509050565b90810390811161298d5790565b9081602091031261035e575161040c816117ad565b60045490939291906142f7906001600160a01b03166107e3565b6001600160a01b039094169384148061441c575b156143f957506004549192509061432c906107e3906001600160a01b031681565b803b1561035e575f8391600460405180968193630d0e30db60e41b83525af191821561093b576143ac936020936143e5575b50600454614376906107e3906001600160a01b031681565b60405163a9059cbb60e01b81526001600160a01b03909216600483015260248201929092529283919082905f9082906044820190565b03925af1801561093b576143bd5750565b6139a69060203d6020116143de575b6143d681836102a4565b8101906142c8565b503d6143cc565b8061092f5f6143f3936102a4565b5f61435e565b6001600160a01b038116300361441357506102d59261458e565b6102d593614ef7565b508247101561430b565b9162ffffff915f6040805161443a81610289565b8281526020810183905201526001600160a01b0381811690851611614483575b6040519361446785610289565b6001600160a01b03908116855216602084015216604082015290565b9261445a565b815160208301519192916001600160a01b03808216908316101561035e57613cda92613f1b926001600160a01b0390811692614504916144d2916040911693015162ffffff1690565b604080516001600160a01b0395861660208201908152959094169084015262ffffff1660608301528160808101613cda565b5190206040516001600160f81b03196020820190815260609590951b6001600160601b031916602182015260358101919091527fe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b5460558201529182906075820190565b603a546001600160a01b0316330361457b57565b63118cdaa760e01b5f523360045260245ffd5b60405163a9059cbb60e01b60208201526001600160a01b03909216602483015260448201929092526102d5916145c7826064810161273e565b6150ba565b156145d357565b60405162461bcd60e51b815260206004820152602860248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4c604482015267495155494449545960c01b6064820152608490fd5b8115614633570490565b634e487b7160e01b5f52601260045260245ffd5b91909180156146dd5761467861467161467e92851515806146d4575b61466c906145cc565b614e17565b9283614e97565b92614e75565b9081019081811161298d5781106146985761040c91614629565b60405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b6044820152606490fd5b50841515614663565b60405162461bcd60e51b815260206004820152602b60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4960448201526a1394155517d05353d5539560aa1b6064820152608490fd5b603a80546001600160a01b039283166001600160a01b0319821681179092559091167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b9081156147e4576147a482826147a9931515806147db575b61479f906145cc565b614e97565b614e75565b90820391821161298d576147c6916147c090614e17565b90614629565b600181019081811161298d5781106146985790565b50851515614796565b60405162461bcd60e51b815260206004820152602c60248201527f556e697377617056324c6962726172793a20494e53554646494349454e545f4f60448201526b155514155517d05353d5539560a21b6064820152608490fd5b602b906148558261484e81612f4f565b1015615125565b61485f825f612f5d565b5061486a6001615125565b6148808151614879845f612f5d565b1115615162565b816148975750506040515f81526020810160405290565b60405191601f811691821560051b808486010193838501920101905b8084106148cb5750508252601f01601f191660405290565b90926020809185518152019301906148b3565b8051601619810181811161298d576148f98161484e81612f4f565b614908601761484e8382612f5d565b6149188351614879836017612f5d565b80614930575050506040515f81526020810160405290565b604051926017601f8316801560051b908181880101956016199087010193010101905b80841061496b5750508252601f01601f191660405290565b9092602080918551815201930190614953565b92919092614990600283511015613fc1565b61499a825161400d565b9384515f19810190811161298d576149b29086612a5f565b5281515f19810190811161298d57805b6149cb57505050565b614a0b6149fa6149e66122cf6149e08561297f565b87612a5f565b6149f36122cf8588612a5f565b9085615019565b90614a058489612a5f565b5161477e565b614a176149e08361297f565b52801561298d575f1901806149c2565b919291906001600160a01b03811615614b47575b60406107e391614a66614a4e8751613a1c565b6001600160a01b038084169083161096929091612b72565b835f614a79614a7488614f3b565b613c58565b93828214614b2357614abb613cda614a9f6401000276a49c895192839160208301613bd9565b8751630251596160e31b81529b8c978896879560048701613c1f565b03925af190811561093b575f945f92614aff575b5015614aeb5790614ae26102d592613c58565b935b9314613873565b9290614af96102d592613c58565b93614ae4565b909450614b1b915060403d604011613d5b57613d4c81836102a4565b90935f614acf565b614abb613cda614a9f73fffd8963efd1fc6a506488495d951d5263988d259c613ccc565b5030614a3b565b91939291906001600160a01b03811615614c7c575b60406107e391614b76614a4e8651613a1c565b835f614b84614a7488614f3b565b6001600160a01b038b16159a909490828c14614c6c5750828214614c4957614bdd613cda614bc16401000276a45b9b895192839160208301613bd9565b8751630251596160e31b81529a8b978896879560048701613c1f565b03925af190811561093b575f935f92614c25575b5015614c1557614c0090613c58565b915b93614c0b575050565b6102d59114613873565b91614c1f90613c58565b91614c02565b909350614c41915060403d604011613d5b57613d4c81836102a4565b90925f614bf1565b614bdd613cda614bc173fffd8963efd1fc6a506488495d951d5263988d25614bb2565b613cda614bc1614bdd929b613ccc565b5030614b63565b919392905f5b614c93825161297f565b811015614da757614ca76122cf8284612a5f565b90614cbd6122cf614cb783612f33565b85612a5f565b91614cc88382614f4a565b5090614cd66140a284612f33565b51916001600160a01b03828116911603614d9757614d2f6107e36107e35f94965b614d018951612992565b871015614d9057614d27614d206122cf614d1a8a612f41565b8c612a5f565b828c613e50565b945b8a613e50565b614d37612d64565b94813b1561035e575f8094614d626040519889968795869463022c0d9f60e01b865260048601612da3565b03925af191821561093b57600192614d7c575b5001614c89565b8061092f5f614d8a936102a4565b5f614d75565b8c94614d29565b614d2f6107e36107e35f96614cf7565b505050509050565b6001600160a01b0393614dc8939192612b909290614426565b1680330361035e5790565b15614dda57565b60405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b6044820152606490fd5b906103e58202918083046103e5148115171561298d576103e5830403614e3957565b60405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b6044820152606490fd5b906103e88202918083046103e8148115171561298d576103e8830403614e3957565b5f92918015918215614ead575b505015614e3957565b8082029450915081158285048214171561298d57614ecb9084614629565b145f80614ea4565b908015614ee35761040c91614629565b634e487b7160e01b5f52600160045260245ffd5b6040516323b872dd60e01b60208201526001600160a01b0392831660248201529290911660448301526064808301939093529181526102d5916145c76084836102a4565b600160ff1b81101561035e5790565b9091906001600160a01b03808416908216808214614fc6571015614fc157915b906001600160a01b03831615614f7c57565b60405162461bcd60e51b815260206004820152601e60248201527f556e697377617056324c6962726172793a205a45524f5f4144445245535300006044820152606490fd5b614f6a565b60405162461bcd60e51b815260206004820152602560248201527f556e697377617056324c6962726172793a204944454e544943414c5f41444452604482015264455353455360d81b6064820152608490fd5b90606060049261503e61502c8685614f4a565b50956001600160a01b03928590613e50565b1660405193848092630240bc6b60e21b82525afa91821561093b575f905f9361508b575b506001600160701b03928316939216916001600160a01b039182169116036150875791565b9091565b6001600160701b0393508391506150b09060603d606011610ea557610e9381836102a4565b5093909150615062565b5f806150e29260018060a01b03169360208151910182865af16150db6129ae565b90836151cd565b805190811515918261510a575b50506150f85750565b635274afe760e01b5f5260045260245ffd5b61511d92506020809183010191016142c8565b155f806150ef565b1561512c57565b60405162461bcd60e51b815260206004820152600e60248201526d736c6963655f6f766572666c6f7760901b6044820152606490fd5b1561516957565b60405162461bcd60e51b8152602060048201526011602482015270736c6963655f6f75744f66426f756e647360781b6044820152606490fd5b60ff5f8051602061522c8339815191525460401c16156151be57565b631afcd79f60e31b5f5260045ffd5b906151f157508051156151e257805190602001fd5b630a12f52160e11b5f5260045ffd5b81511580615222575b615202575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b156151fa56fef0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0ea264697066735822122028da49c44c096942378115c02739e31f194dda1faaef8e389be874d6c214dea464736f6c634300081a0033

Deployed Bytecode Sourcemap

1056:36109:1:-:0;;;;;;;;;-1:-1:-1;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;:::o;:::-;;:::i;:::-;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;:::o;:::-;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;:::o;:::-;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;:::o;:::-;17628:10;1056:36109;;;17628:10;1056:36109;;:::i;:::-;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;:::o;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;;-1:-1:-1;;1056:36109:1;;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;-1:-1:-1;1056:36109:1;;;;;;:::o;:::-;-1:-1:-1;1056:36109:1;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;:::o;:::-;;;;;;:::i;:::-;;;-1:-1:-1;;1056:36109:1;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;23152:17;1056:36109;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;23152:17;:::i;:::-;1056:36109;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;1056:36109:1;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;1056:36109:1;;;;;147:29:0;1056:36109:1;;;;;;;;;;;;;-1:-1:-1;;1056:36109:1;;;;270:24:0;1056:36109:1;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;;-1:-1:-1;;1056:36109:1;;;;1681:62:2;;:::i;:::-;2179:7:4;1056:36109:1;;;;2523:9:4;2519:62;;1056:36109:1;;;2179:7:4;1056:36109:1;3057:22:4;1056:36109:1;;;930:10:10;1056:36109:1;;3057:22:4;1056:36109:1;2519:62:4;2555:15;;;1056:36109:1;2555:15:4;1056:36109:1;;2555:15:4;1056:36109:1;;;;;;-1:-1:-1;;1056:36109:1;;;;;;1681:62:2;;:::i;:::-;36368:5:1;36361:12;;1056:36109;;;36412:14;1056:36109;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;-1:-1:-1;;1056:36109:1;;;;;;;:::i;:::-;2569:103:5;;:::i;:::-;1698:72:4;;:::i;:::-;3069:59:1;16576:15;;;1056:36109;3077:15;:27;;3069:59;:::i;:::-;16640:15;;;16632:56;1056:36109;;16640:19;;16632:56;:::i;:::-;1056:36109;;-1:-1:-1;;;;;1056:36109:1;16703:28;16699:428;;1056:36109;;;17219:21;;17151:40;;-1:-1:-1;;;;;1056:36109:1;;;17151:40;;:::i;:::-;1056:36109;;17219:21;:::i;:::-;1056:36109;;17287:15;;;1056:36109;;-1:-1:-1;;17287:15:1;:29;;-1:-1:-1;;;;;1056:36109:1;;-1:-1:-1;;;;;1056:36109:1;;;17287:29;;17283:112;;1056:36109;17417:270;1056:36109;;;17478:41;;;;;-1:-1:-1;17478:41:1;17533:24;;;1056:36109;-1:-1:-1;;;;;1056:36109:1;;;;;;17595:61;;-1:-1:-1;;;;;1056:36109:1;17595:61;1056:36109;;17628:10;;;1056:36109;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;17628:10;1056:36109;17595:61;;;17287:15;17595:61;;;:::i;:::-;;1056:36109;;17595:61;;;;;;:::i;:::-;1056:36109;;:::i;:::-;;;;17665:10;17287:15;17571:106;;1056:36109;17417:270;:::i;:::-;17719:23;17698:79;17719:23;;;1056:36109;17706:36;;;17698:79;:::i;:::-;17788:215;;17478:41;1056:36109;2634:1:5;;1787;3171:21;1056:36109:1;2991:208:5;17788:215:1;1056:36109;;17817:20;;:11;;-1:-1:-1;;;;;1056:36109:1;17817:11;1056:36109;17817:20;:31;;;;;17628:10;1056:36109;-1:-1:-1;;;17817:31:1;;1056:36109;17817:31;;1056:36109;;;;-1:-1:-1;;1056:36109:1;;;;;;-1:-1:-1;;17817:31:1;;;;;;-1:-1:-1;17817:31:1;;;1056:36109;17889:16;1056:36109;17817:31;17947:45;17817:31;;;;;17788:215;-1:-1:-1;17889:16:1;1056:36109;-1:-1:-1;;;;;1056:36109:1;;;;17881:52;;;;:::i;:::-;;17947:45;:::i;:::-;17788:215;;17817:31;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;:::i;17478:41::-;17503:16;;;1056:36109;-1:-1:-1;;;;;1056:36109:1;17478:41;;17283:112;1056:36109;;17417:270;;-1:-1:-1;17332:22:1;;-1:-1:-1;;;;;1056:36109:1;;-1:-1:-1;;;;;1056:36109:1;;;;17332:22;17380:4;17283:112;;;;16699:428;1056:36109;;-1:-1:-1;;;;;1056:36109:1;;;16782:76;1056:36109;;16790:9;:28;;16782:76;:::i;:::-;16908:27;1056:36109;;16790:9;16908:27;:::i;:::-;16953:10;16949:168;;16699:428;;;;16949:168;-1:-1:-1;17008:10:1;;;17059:43;17008:10;;17000:43;;;;:::i;:::-;;17059;:::i;:::-;16949:168;;;1056:36109;;;;;;-1:-1:-1;;1056:36109:1;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1056:36109:1;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;1681:62:2;;:::i;:::-;37000:47:1;-1:-1:-1;;;;;1056:36109:1;;37008:22;;37000:47;:::i;:::-;1056:36109;;-1:-1:-1;;;37106:49:1;;37149:4;1056:36109;37106:49;;1056:36109;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;37106:49;;;;;;;;;-1:-1:-1;37106:49:1;;;1056:36109;37106:49;;:::i;:::-;;;;;1056:36109;37106:49;1056:36109;37106:49;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;1056:36109;;;;;;-1:-1:-1;;1056:36109:1;;;;;;;;;:::i;:::-;1681:62:2;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;36652:43;36660:18;;;36652:43;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;;;;-1:-1:-1;1056:36109:1;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;2569:103:5;;;;;:::i;:::-;1698:72:4;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;4444:2732;;4690:65;4698:25;;;4690:65;:::i;:::-;4765:48;4773:12;;;4765:48;:::i;:::-;-1:-1:-1;;;;;;;1056:36109:1;4859:21;4855:429;;1056:36109;5307:26;;5354:14;5307:26;;;:::i;:::-;5354:14;;:::i;:::-;5379:154;;;;5448:8;5428:4;;5448:8;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;-1:-1:-1;;5580:22:1;;5576:56;;5379:154;5664:126;;;;1056:36109;;5689:33;;:23;;-1:-1:-1;;;;;1056:36109:1;5689:23;1056:36109;5689:33;1056:36109;;-1:-1:-1;;;5689:48:1;;5731:4;1056:36109;5689:48;;1056:36109;;5689:48;;1056:36109;;;;;;5689:48;;;;;;;-1:-1:-1;5689:48:1;;;5664:126;;;;1056:36109;;-1:-1:-1;;;5885:13:1;;;1056:36109;;;5885:13;;;;;;;;-1:-1:-1;5885:13:1;;;5664:126;-1:-1:-1;1056:36109:1;;-1:-1:-1;;;6049:18:1;;1056:36109;6049:18;1056:36109;;;6049:18;;;;;;;;-1:-1:-1;;;6049:18:1;;;5664:126;-1:-1:-1;;;;;;1056:36109:1;;;;;;;6123:17;;;-1:-1:-1;;;;;1056:36109:1;;;;;6123:63;;;;;1056:36109;;-1:-1:-1;;;6214:51:1;;-1:-1:-1;;;;;1056:36109:1;;;6214:51;;1056:36109;;5885:13;;1056:36109;;;;;;6214:51;;;;;;;:69;:51;6312:71;6214:51;-1:-1:-1;6214:51:1;;;6123:63;6214:69;;:::i;:::-;6312:71;:::i;:::-;6440:69;;;;-1:-1:-1;6440:69:1;;;6532:38;;;;6552:4;6532:38;;6618:12;;:::i;:::-;6580:51;;;;;;-1:-1:-1;1056:36109:1;;6580:51;1056:36109;;;;;;;;;;;;6580:51;;1056:36109;6580:51;;;:::i;:::-;;;;;;;;;;;6532:38;-1:-1:-1;6642:413:1;;;-1:-1:-1;1056:36109:1;;6683:33;;:23;;-1:-1:-1;;;;;1056:36109:1;6683:23;1056:36109;6683:33;1056:36109;;-1:-1:-1;;;6683:48:1;;6725:4;1056:36109;6683:48;;1056:36109;;;5885:13;1056:36109;;;;6683:48;;;;;;:67;:48;-1:-1:-1;6683:48:1;;;:67;;:::i;:::-;6764:31;;;;;;1056:36109;;-1:-1:-1;;;6764:31:1;;1056:36109;6764:31;;1056:36109;;;;-1:-1:-1;;1056:36109:1;;;;;;-1:-1:-1;;6764:31:1;;;;;;;1056:36109;6764:31;7064:105;6764:31;;;6642:413;6836:10;6888:45;-1:-1:-1;6836:10:1;;;;;6828:46;;;;:::i;6888:45::-;7085:25;;;7064:105;:::i;:::-;2634:1:5;1787;3171:21;1056:36109:1;2991:208:5;6764:31:1;;;-1:-1:-1;6764:31:1;;;:::i;:::-;;;;6683:48;;;;5885:13;6683:48;5885:13;6683:48;;;;;;;:::i;:::-;;;;6642:413;1056:36109;;-1:-1:-1;;;6976:49:1;;7014:10;1056:36109;6976:49;;1056:36109;;5885:13;;1056:36109;;;;;;6976:49;;;;;;;1056:36109;6976:49;7064:105;6976:49;:68;:49;-1:-1:-1;6976:49:1;;;:68;;:::i;:::-;6642:413;;;6580:51;;;-1:-1:-1;6580:51:1;;;:::i;:::-;;;;6532:38;6560:10;6532:38;;;6440:69;-1:-1:-1;6440:69:1;;;6123:63;;;;6049:18;-1:-1:-1;;;;;6049:18:1;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;5885:13;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;5689:48;;;;;;;;;;;;;;:::i;:::-;;;;5664:126;1056:36109;;-1:-1:-1;;;5741:49:1;;5779:10;1056:36109;5741:49;;1056:36109;5741:49;1056:36109;;;5741:49;;;;;;;;-1:-1:-1;5741:49:1;;;5664:126;;;;;5741:49;;;;;;;;;;;;;;:::i;:::-;;;;5576:56;5628:4;;-1:-1:-1;5576:56:1;;5379:154;5524:8;5499:10;;5524:8;;:::i;:::-;5379:154;;4855:429;4904:9;;;4896:69;4904:9;;;:21;;4896:69;:::i;:::-;1056:36109;;4990:4;;5354:14;;-1:-1:-1;;;;;1056:36109:1;4904:9;5072:20;4904:9;;5072:20;:::i;:::-;5110:10;5106:168;;4855:429;;;;;;5106:168;-1:-1:-1;5165:10:1;;;5216:43;5165:10;;5157:43;;;;:::i;5216:::-;5106:168;;;1056:36109;;;;;;-1:-1:-1;;1056:36109:1;;;;;;2179:7:4;1056:36109:1;;;;;;;;;;;;-1:-1:-1;;1056:36109:1;;;;;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;12829:7;3069:59;13071:55;13007:43;1056:36109;;;:::i;:::-;2569:103:5;;;;;;;;;;;;;;:::i;:::-;1698:72:4;;:::i;:::-;3077:15:1;:27;;3069:59;:::i;:::-;11814:1765;;;12159:12;12151:48;12159:12;;;12151:48;:::i;:::-;-1:-1:-1;;;;;;;1056:36109:1;12245:21;12241:429;;1056:36109;12694:26;12829:7;12741:14;12694:26;;12786:51;12694:26;;;:::i;12741:14::-;12820:7;;;;;;;;:::i;:::-;;:::i;:::-;12829;;:::i;:::-;12786:51;;;:::i;:::-;12847:150;;;;12914:8;12896:4;;12914:8;;:::i;:::-;13015:18;13026:7;;;;;:::i;13015:18::-;-1:-1:-1;;;;;1056:36109:1;;;13015:18;13007:43;:::i;:::-;1056:36109;;;;;:::i;:::-;13071:55;;;:::i;:::-;13181:15;13158:50;:40;13176:21;;13181:15;;;:::i;:::-;13176:21;;;:::i;13158:50::-;1056:36109;;-1:-1:-1;;;13158:61:1;;-1:-1:-1;;;;;1056:36109:1;;;13158:61;;1056:36109;;;13158:61;;1056:36109;;;;;;13158:61;;;;;;;13321;13158;;;-1:-1:-1;13158:61:1;;;12847:150;1056:36109;13339:21;;13321:50;1056:36109;13229:60;13321:40;1056:36109;;;13158:61;1056:36109;;;;;;:::i;:::-;13229:60;:::i;:::-;13344:15;;;;:::i;:::-;13339:21;;:::i;13321:50::-;1056:36109;;-1:-1:-1;;;13321:61:1;;-1:-1:-1;;;;;1056:36109:1;;;;13321:61;;1056:36109;;;;;-1:-1:-1;1056:36109:1;;;;;;;;;13321:61;;;;;;;;;;13411:41;13321:80;13419:15;13321:61;1056:36109;13321:61;13462:110;13321:61;-1:-1:-1;13321:61:1;;;:80;;:::i;:::-;13419:15;;;;:::i;:::-;13411:41;;:::i;:::-;1056:36109;13483:30;;13462:110;:::i;:::-;2634:1:5;1787;3171:21;1056:36109:1;2991:208:5;2634:1;1056:36109:1;;;;;;;:::i;13158:61::-;;;;13339:21;13321:50;13158:61;13229:60;13321:40;13158:61;;1056:36109;13158:61;13339:21;13158:61;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;12847:150;12988:8;12965:10;;12988:8;;:::i;:::-;12847:150;;12241:429;12290:9;;;;;12282:69;12290:9;;:21;;12282:69;:::i;:::-;12376:4;1056:36109;12786:51;1056:36109;12829:7;12741:14;1056:36109;;;;;;;;;;;;12290:9;12458:20;12290:9;;12458:20;:::i;:::-;12496:10;12492:168;;12241:429;;;;;;;;;12492:168;-1:-1:-1;12551:10:1;;;12602:43;12551:10;;12543:43;;;;:::i;12602:::-;12492:168;;;1056:36109;;;;;;-1:-1:-1;;1056:36109:1;;;;240:24:0;1056:36109:1;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;;-1:-1:-1;;1056:36109:1;;;;1681:62:2;;:::i;:::-;3185:6;1056:36109:1;;-1:-1:-1;;;;;;1056:36109:1;;;;;;;-1:-1:-1;;;;;1056:36109:1;3233:40:2;1056:36109:1;;3233:40:2;1056:36109:1;;;;;;;-1:-1:-1;;1056:36109:1;;;;1681:62:2;;:::i;:::-;1698:72:4;;:::i;:::-;2791:4;1056:36109:1;;2781:14:4;1056:36109:1;;;2781:14:4;1056:36109:1;2810:20:4;1056:36109:1;;;930:10:10;1056:36109:1;;2810:20:4;1056:36109:1;;;;;:::i;:::-;2569:103:5;;;;;;;;:::i;:::-;1698:72:4;;:::i;:::-;7264:2228:1;;-1:-1:-1;;;;;1056:36109:1;;;;7264:2228;7511:65;7519:25;;;7511:65;:::i;:::-;7586:55;7594:15;;;7586:55;:::i;:::-;-1:-1:-1;;;;;;;1056:36109:1;7687:21;7683:181;;1056:36109;-1:-1:-1;;;;;;;1056:36109:1;7910:22;7906:69;;1056:36109;;;-1:-1:-1;;;8061:13:1;;1056:36109;8061:13;1056:36109;;;8061:13;;;;;;;;-1:-1:-1;8061:13:1;;;1056:36109;-1:-1:-1;1056:36109:1;;-1:-1:-1;;;8172:18:1;;1056:36109;8172:18;1056:36109;;;8172:18;;;;;;;;-1:-1:-1;;;8172:18:1;;;1056:36109;-1:-1:-1;;;;;;1056:36109:1;;;;;8246:17;;;;;8334:68;;-1:-1:-1;;;;;1056:36109:1;;;;;8246:63;;;;;8334:68;;:::i;:::-;8431:26;;;8472:71;8431:26;;;;:::i;:::-;8480:14;;;;;:::i;:::-;:29;;8472:71;:::i;:::-;8557:468;;;8609:4;8629:8;8609:4;8670:26;8609:4;;;8629:8;;:::i;:::-;8670:20;:9;;:20;:::i;:::-;:26;:::i;:::-;8744:10;8740:184;;8557:468;;;9081:63;;;-1:-1:-1;9081:63:1;;;9167:38;;;;9187:4;9167:38;;9253:12;;:::i;:::-;9215:51;;;;;;-1:-1:-1;1056:36109:1;;9215:51;1056:36109;;;;;;;;;;;;9215:51;;1056:36109;9215:51;;;:::i;:::-;;;;;;;;;;;9167:38;9277:209;;;1056:36109;2634:1:5;;1787;3171:21;1056:36109:1;2991:208:5;9277:209:1;1056:36109;;9306:20;;:11;;-1:-1:-1;;;;;1056:36109:1;9306:11;1056:36109;9306:20;:31;;;;;1056:36109;;-1:-1:-1;;;9306:31:1;;1056:36109;9306:31;;1056:36109;;;;-1:-1:-1;;1056:36109:1;;;;;;-1:-1:-1;;9306:31:1;;;;;;-1:-1:-1;9306:31:1;;1056:36109;9306:31;9430:45;9306:31;;;;;9277:209;9378:10;;9370:46;;;;:::i;9306:31::-;;;;;;;:::i;:::-;;;;9215:51;;;-1:-1:-1;9215:51:1;;;:::i;:::-;;;;9167:38;9195:10;9167:38;;;9081:63;;-1:-1:-1;9081:63:1;;;8740:184;-1:-1:-1;8805:10:1;;;8862:43;8805:10;;8797:43;;;;:::i;8862:::-;8740:184;;;8557:468;9001:8;8976:10;;;9001:8;;:::i;:::-;8557:468;;8246:63;;;;8172:18;-1:-1:-1;;;;;8172:18:1;;8334:68;8172:18;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;8172:18:1;-1:-1:-1;8172:18:1;;-1:-1:-1;8172:18:1;;8061:13;;;;;;;;;;;;;;;:::i;:::-;;;;;7906:69;7960:4;;-1:-1:-1;7906:69:1;;7683:181;-1:-1:-1;1056:36109:1;;-1:-1:-1;;;;;1056:36109:1;;-1:-1:-1;7763:4:1;7781:72;7789:9;:24;-1:-1:-1;7789:24:1;7781:72;:::i;:::-;7683:181;;1056:36109;;;;;;-1:-1:-1;;1056:36109:1;;;;1891:6:2;1056:36109:1;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;-1:-1:-1;;1056:36109:1;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;19945:17;1056:36109;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;19945:17;:::i;1056:36109::-;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;1056:36109:1;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;1681:62:2;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;36812:43;36820:18;;;36812:43;:::i;:::-;-1:-1:-1;1056:36109:1;36865:14;1056:36109;;;-1:-1:-1;1056:36109:1;;;;;;;;;;;;;;;-1:-1:-1;1056:36109:1;;;;;;;;-1:-1:-1;;1056:36109:1;;;;;119:22:0;1056:36109:1;;;;;;;;;;-1:-1:-1;;1056:36109:1;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;28720:16;1056:36109;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;28720:16;:::i;1056:36109::-;;;;;;-1:-1:-1;;1056:36109:1;;;;;;;;;:::i;:::-;1681:62:2;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;36507:43;36515:18;;;36507:43;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;36560:19;1056:36109;;;36560:19;1056:36109;-1:-1:-1;1056:36109:1;;;;;-1:-1:-1;;1056:36109:1;;;;;;;:::i;:::-;2569:103:5;;:::i;:::-;1698:72:4;;:::i;:::-;3069:59:1;18181:15;;;1056:36109;3077:15;:27;;3069:59;:::i;:::-;18244:22;;;1056:36109;18236:67;1056:36109;;18244:26;;18236:67;:::i;:::-;1056:36109;;-1:-1:-1;;1056:36109:1;-1:-1:-1;;;;;1056:36109:1;18349:28;18345:210;;1056:36109;18601:15;;;1056:36109;;18601:15;;-1:-1:-1;;18601:29:1;;-1:-1:-1;;;;;1056:36109:1;;;18601:29;;18597:112;;1056:36109;18730:272;18763:16;;;1056:36109;;;18793:41;;;;;;-1:-1:-1;18793:41:1;18848:24;;;1056:36109;;;-1:-1:-1;;;;;1056:36109:1;;;;-1:-1:-1;;;;;1056:36109:1;;;;18944:10;18910:61;1056:36109;18944:10;;;1056:36109;;;;;;;;;;;18910:61;;-1:-1:-1;;;;;1056:36109:1;;;18910:61;1056:36109;;:::i;:::-;;;;18980:10;18601:15;18886:106;;1056:36109;18730:272;:::i;:::-;1056:36109;19071:78;19027:33;1056:36109;;;;;;;;;;;;;19027:33;:::i;:::-;19079:14;;;;;:::i;:::-;1056:36109;;-1:-1:-1;19079:40:1;19071:78;:::i;:::-;19168:286;;18793:41;19465:229;;;18793:41;-1:-1:-1;;1056:36109:1;;;19704:34;;1056:36109;19465:229;1056:36109;;19494:20;;:11;;-1:-1:-1;;;;;1056:36109:1;19494:11;1056:36109;19494:20;1056:36109;;;19494:38;;;;;;18944:10;1056:36109;-1:-1:-1;;;19494:38:1;;1056:36109;19494:38;;1056:36109;;;;-1:-1:-1;;1056:36109:1;;;;;;-1:-1:-1;;19494:38:1;;;;;;;-1:-1:-1;19494:38:1;;;1056:36109;19573:16;19638:45;19494:38;;;1056:36109;19494:38;;;-1:-1:-1;19573:16:1;1056:36109;-1:-1:-1;;;;;1056:36109:1;;;;;;19565:59;;;;;:::i;19638:45::-;19465:229;;;19168:286;19210:26;:9;:20;:9;;:20;:::i;:26::-;19276:10;19272:172;19168:286;19272:172;-1:-1:-1;18980:10:1;;;19386:43;18980:10;;19325:43;;;;:::i;19386:::-;19272:172;19168:286;;18793:41;18818:16;;;1056:36109;-1:-1:-1;;;;;1056:36109:1;18793:41;;18597:112;1056:36109;;-1:-1:-1;;;;;1056:36109:1;;;18694:4;;-1:-1:-1;18597:112:1;;18345:210;1056:36109;;18404:4;;-1:-1:-1;18422:21:1;;-1:-1:-1;;;;;1056:36109:1;;;18422:21;18457:87;1056:36109;;18465:9;:35;;18457:87;:::i;:::-;18345:210;;1056:36109;;;;;;-1:-1:-1;;1056:36109:1;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;;-1:-1:-1;;1056:36109:1;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;1056:36109:1;301:47:0;1056:36109:1;;;;;-1:-1:-1;1056:36109:1;;;;;;;;;;;;;;;;;-1:-1:-1;;1056:36109:1;;;;182:27:0;1056:36109:1;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;3069:59;15022:40;1056:36109;14437:10;1056:36109;;;:::i;:::-;2569:103:5;;;;;;;;;;;;;:::i;3069:59:1:-;13672:1397;14019:15;14011:56;14019:15;;;14011:56;:::i;:::-;-1:-1:-1;;;;;;;1056:36109:1;14113:21;14109:181;;1056:36109;14310:55;14429:73;1056:36109;;;;;;:::i;:::-;14310:55;;;:::i;:::-;14407:10;14437:16;14407:10;14390:28;14407:10;;;:::i;:::-;1056:36109;14390:28;;:::i;:::-;14437:10;;;;:::i;:::-;1056:36109;14437:16;:::i;14429:73::-;14533:51;14567:7;;;;;:::i;:::-;14576;;;;;:::i;:::-;14533:51;;;:::i;:::-;14594:417;;;;14700:28;14661:10;;;;;;;:::i;:::-;1056:36109;14643:4;;14661:10;;:::i;:::-;14700:22;14712:10;;;:::i;:::-;1056:36109;14700:9;:22;:::i;:28::-;14768:10;14764:172;;14594:417;;;1056:36109;;;:::i;:::-;15022:40;;:::i;14764:172::-;-1:-1:-1;14825:10:1;;;14878:43;14825:10;;14817:43;;;;:::i;14878:::-;14764:172;;;14594:417;15000:10;;;;;;:::i;:::-;1056:36109;14977:10;;15000;;:::i;:::-;14594:417;;14109:181;1056:36109;;-1:-1:-1;;;;;1056:36109:1;;-1:-1:-1;14161:4:1;;-1:-1:-1;14429:73:1;;14310:55;;14207:72;14215:9;:24;-1:-1:-1;14215:24:1;14207:72;:::i;:::-;14109:181;;;;;1056:36109;;;;;;-1:-1:-1;;1056:36109:1;;;;;;;;;:::i;:::-;1681:62:2;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;2808:22:2;2804:91;;2923:8;;;:::i;2804:91::-;2853:31;;;-1:-1:-1;2853:31:2;-1:-1:-1;1056:36109:1;;;-1:-1:-1;2853:31:2;1056:36109:1;;;;;;-1:-1:-1;;1056:36109:1;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;;;;;1056:36109:1;;;4104:16:3;1056:36109:1;;;;;;;;;;4104:16:3;;1056:36109:1;4104:16:3;1056:36109:1;-1:-1:-1;;;;;1056:36109:1;;;;4181:33:3;;;;1056:36109:1;4179:36:3;:93;;;;1056:36109:1;4175:151:3;;;4439:1;4335:18;;;1056:36109:1;-1:-1:-1;;;;;1056:36109:1;-1:-1:-1;;;;;;;;;;;1056:36109:1;;;-1:-1:-1;;;;;;;;;;;1056:36109:1;;4335:18:3;4363:67;;4439:1;:::i;:::-;4450:101;;1056:36109:1;4450:101:3;4484:23;-1:-1:-1;;;1056:36109:1;-1:-1:-1;;;;;;;;;;;1056:36109:1;;-1:-1:-1;;;;;;;;;;;1056:36109:1;;4484:23:3;1056:36109:1;;4352:1:3;1056:36109:1;;4526:14:3;;1056:36109:1;;4526:14:3;1056:36109:1;4363:67:3;4397:22;1056:36109:1;-1:-1:-1;;;1056:36109:1;-1:-1:-1;;;;;;;;;;;1056:36109:1;;;-1:-1:-1;;;;;;;;;;;1056:36109:1;;4397:22:3;4439:1;:::i;4175:151::-;4295:20;;;-1:-1:-1;4295:20:3;1056:36109:1;-1:-1:-1;4295:20:3;4179:93;4229:4;4221:25;:30;;-1:-1:-1;4221:30:3;:50;;4179:93;4219:53;;4179:93;;;4221:50;4270:1;1056:36109:1;;-1:-1:-1;;;;;1056:36109:1;4255:16:3;4221:50;;;4181:33;1056:36109:1;4213:1:3;-1:-1:-1;;;;;1056:36109:1;;4199:15:3;4181:33;;1056:36109:1;;;-1:-1:-1;;1056:36109:1;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;21796:16;1056:36109;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;21796:16;:::i;1056:36109::-;;;;;;-1:-1:-1;;1056:36109:1;;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;;;;;;;:::i;2569:103:5:-;;;:::i;:::-;1698:72:4;;:::i;:::-;3069:59:1;23126:15;;;1056:36109;3077:15;:27;;3069:59;:::i;:::-;-1:-1:-1;23182:68:1;23214:1;23190:13;;1056:36109;23190:25;23182:68;:::i;:::-;23269:15;;;23261:56;1056:36109;;23269:19;;23261:56;:::i;:::-;23380:30;:12;;;;:30;:::i;:::-;23328:82;;;;-1:-1:-1;;23328:82:1;;-1:-1:-1;;;;;1056:36109:1;;23455:21;23451:443;;2569:103:5;23978:21:1;23917:33;1056:36109;;23917:33;;:::i;:::-;1056:36109;;23978:21;:::i;:::-;1056:36109;;24014:34;24025:16;:13;;:16;:::i;:::-;;1056:36109;;:::i;:::-;24014:34;1056:36109;;;;;22855:22;1056:36109;;;;;;22881:22;22855:48;22750:160;;24014:34;:72;;;2569:103:5;24010:4407:1;;;24187:15;;;24868:55;24187:15;;;;1056:36109;24162:61;1056:36109;;;;;;;;;;;;;;24162:61;:::i;:::-;24237:182;;;;24311:15;1056:36109;;24290:4;;24311:15;;:::i;:::-;24489:18;24459:16;;:::i;:::-;24489:18;;;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;;24489:18;24521:20;;;;;:::i;:::-;24580:30;:12;;;;:30;:::i;:::-;24649:16;;;;;;:::i;:::-;24680:20;;;;;;:::i;:::-;24714:19;;;;;:::i;:::-;24795:15;;;1056:36109;;24795:15;;24770:62;;24795:15;;1056:36109;-1:-1:-1;;;;;1056:36109:1;24162:61;:::i;24770:62::-;1056:36109;24906:16;;1056:36109;;24187:15;1056:36109;-1:-1:-1;;;24868:55:1;;-1:-1:-1;;;;;1056:36109:1;;;24868:55;;;1056:36109;;;;;24906:16;;;23380:12;;1056:36109;;;;;;;;;24868:55;;;;;;;;;;;-1:-1:-1;24868:55:1;;;24237:182;1056:36109;;;;24993:15;23380:12;1056:36109;;25083:15;1056:36109;;25125:55;1056:36109;;;;;;;;;;;;24993:15;;:::i;:::-;1056:36109;;;;-1:-1:-1;;;;;1056:36109:1;;;;-1:-1:-1;;;;;1056:36109:1;;;25083:15;1056:36109;-1:-1:-1;;;;;1056:36109:1;;;;24187:15;1056:36109;-1:-1:-1;;;25125:55:1;;-1:-1:-1;;;;;1056:36109:1;;;24868:55;25125;;1056:36109;;;;;;;;;;;;;;25125:55;;;;;;;;;;28427:75;25125:55;28448:23;25125:55;:74;:55;-1:-1:-1;25125:55:1;;;:74;;:::i;:::-;24010:4407;;28448:23;1056:36109;28435:36;;;28427:75;:::i;:::-;2634:1:5;;1787;3171:21;1056:36109:1;2991:208:5;24868:55:1;25125;24868;;;;;;24993:15;23380:12;24868:55;;25083:15;24868:55;1056:36109;24868:55;1056:36109;24868:55;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;24237:182;24403:15;1056:36109;;24377:10;;24403:15;;:::i;:::-;24237:182;;24010:4407;25220:34;25231:16;:13;;;;;;:16;:::i;25220:34::-;:72;;;24010:4407;25216:3201;;;25356:15;;25749:71;25983:55;25356:15;25658:18;25356:15;;25690:20;25852:27;25356:15;;;;1056:36109;25331:61;1056:36109;;;;;;;;;;;;;25331:61;25406:182;;;;1056:36109;;25480:15;;25459:4;25480:15;;:::i;:::-;25628:16;;:::i;:::-;25658:18;;;;;;:::i;:::-;25690:20;;;:::i;:::-;1056:36109;;-1:-1:-1;;;;;1056:36109:1;;;25749:71;;:::i;:::-;25861:17;1056:36109;;25861:17;:::i;:::-;25852:27;;:::i;:::-;1056:36109;25918:12;;;:30;:12;;:30;:::i;:::-;-1:-1:-1;1056:36109:1;26021:16;;1056:36109;;25356:15;1056:36109;-1:-1:-1;;;25983:55:1;;-1:-1:-1;;;;;1056:36109:1;;;25983:55;;;1056:36109;;;;;26021:16;;1056:36109;;-1:-1:-1;26021:16:1;23380:12;;1056:36109;;;;;;;;;25983:55;;;;;;;;;;;-1:-1:-1;25983:55:1;;;25406:182;1056:36109;26430:55;1056:36109;;;;26109:15;23380:12;1056:36109;;;26152:252;1056:36109;;;;;;;;;;;26102:4;;26109:15;;:::i;:::-;1056:36109;;-1:-1:-1;;;;;1056:36109:1;26315:12;;1056:36109;;;:::i;:::-;;;;26102:4;26270:120;;;1056:36109;26152:252;:::i;26270:120::-;26152:252;:::i;:::-;-1:-1:-1;1056:36109:1;-1:-1:-1;;;;;1056:36109:1;;;26430:55;;;;;;;;;;28427:75;26430:55;28448:23;26430:55;:74;:55;-1:-1:-1;26430:55:1;;;:74;;:::i;:::-;25216:3201;24010:4407;;25983:55;26152:252;25983:55;;;;1056:36109;25983:55;26109:15;23380:12;25983:55;;1056:36109;25983:55;26430;25983;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;25406:182;1056:36109;;25572:15;;25546:10;25572:15;;:::i;:::-;25406:182;;25216:3201;26536:13;;;;;;26525:34;26536:16;:13;;:16;:::i;:::-;;1056:36109;;:::i;26525:34::-;:72;;;25216:3201;26521:1896;;;26653:12;27350:29;27258:66;26746:15;26815:281;27415:55;26653:12;27167:19;26653:12;1056:36109;26653:12;26980:42;26653:12;;26980:42;26721:61;26653:30;:12;;;;:30;:::i;:::-;26746:15;;;;;;;;1056:36109;;;;;;;;;;;26721:61;1056:36109;;;;;26980:42;;;23380:12;26980:42;;;:::i;:::-;;1056:36109;;26980:42;;;;;;:::i;:::-;1056:36109;;:::i;:::-;;;;27052:10;23380:12;26935:147;;1056:36109;26152:252;:::i;26815:281::-;27136:16;;:::i;:::-;27167:19;;;;;;:::i;:::-;27200;;;;;:::i;:::-;1056:36109;;-1:-1:-1;;;;;1056:36109:1;27258:66;:::i;27350:29::-;-1:-1:-1;1056:36109:1;27453:16;;1056:36109;;;;-1:-1:-1;;;27415:55:1;;-1:-1:-1;;;;;1056:36109:1;;;27415:55;;;1056:36109;;;;;27453:16;;1056:36109;;23380:12;;1056:36109;;;;;;;;;27415:55;;;;;;;;;;;-1:-1:-1;27415:55:1;;;26521:1896;1056:36109;;27544:15;27586:55;1056:36109;;;;;;23380:12;1056:36109;;;;;;;;;;27415:55;1056:36109;27415:55;;;;27544:15;27586:55;27415;;;23380:12;27415:55;;;;;;;;;;;:::i;:::-;;;;;;;;;;;26521:1896;27692:13;;;;27681:34;27692:16;:13;;:16;:::i;27681:34::-;:72;;;26521:1896;27677:740;;26521:1896;;;;;28448:23;28427:75;26521:1896;24010:4407;;27677:740;28427:75;1056:36109;;;28149:257;1056:36109;;;28006:42;27841:281;1056:36109;28006:42;28448:23;1056:36109;;;;;28006:42;;;23380:12;28006:42;;;:::i;:::-;;1056:36109;;28006:42;;;;;;:::i;:::-;1056:36109;;:::i;:::-;;;;28078:10;23380:12;27961:147;;1056:36109;27918:4;27841:281;;:::i;:::-;1056:36109;;;;28218:16;;;1056:36109;-1:-1:-1;;;;;1056:36109:1;28317:12;;;;1056:36109;;;:::i;:::-;;;;27918:4;23380:12;28272:120;;1056:36109;26152:252;:::i;28149:257::-;27677:740;;;;;;27681:72;27730:13;27719:34;27730:16;:13;;:16;:::i;27719:34::-;27681:72;;26525;26574:13;26563:34;26574:16;:13;;:16;:::i;26563:34::-;26525:72;;25220;25269:13;25258:34;25269:16;:13;;:16;:::i;25258:34::-;25220:72;;24014;24063:13;24052:34;24063:16;:13;;:16;:::i;24052:34::-;24014:72;;23451:443;1056:36109;;;;23492:76;1056:36109;;23500:9;:28;;23492:76;:::i;:::-;23621:4;1056:36109;23593:4;;1056:36109;-1:-1:-1;;;;;1056:36109:1;;23675:27;1056:36109;;23500:9;23675:27;:::i;:::-;23720:10;23716:168;;23451:443;;;;23716:168;-1:-1:-1;23775:10:1;;;23826:43;23775:10;;23767:43;;;;:::i;23826:::-;23716:168;;;1056:36109;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1056:36109:1;;;;;;;;:::o;:::-;;:::i;:::-;-1:-1:-1;;1056:36109:1;;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;-1:-1:-1;1056:36109:1;;;;:::o;:::-;;;:::o;:::-;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;:::i;:::-;;;24077:1;1056:36109;;;;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;1056:36109:1;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;1056:36109:1;;;;:::o;:::-;;;;;-1:-1:-1;;;;;;1056:36109:1;;;;;;;;;;-1:-1:-1;;;;;;1056:36109:1;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;:::i;:::-;23214:1;1056:36109;;;-1:-1:-1;;1056:36109:1;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;32820:250;33007:9;1056:36109;-1:-1:-1;;;;;1056:36109:1;32980:82;;1056:36109;;;;33018:43;;32820:250;33018:43;:::i;:::-;32980:82;;:::i;:::-;1056:36109;32820:250;:::o;1056:36109::-;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;1056:36109:1;;;;;;:::o;:::-;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;-1:-1:-1;1056:36109:1;;;;;;;;-1:-1:-1;;1056:36109:1;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;:::o;:::-;;12834:1;1056:36109;;;;;;;:::o;:::-;;;;;;;;;;;;:::o;:::-;;;;;:::i;:::-;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;4278:1:20;1056:36109:1;;;;;;;:::o;:::-;;11584:1;1056:36109;;;;;;;:::o;:::-;;563:2:14;1056:36109:1;;;;;;;:::o;:::-;;;;;;;;;;:::o;:::-;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;2569:103:5;;;:::i;:::-;1698:72:4;;:::i;:::-;3069:59:1;19919:15;;;1056:36109;3077:15;:27;;3069:59;:::i;:::-;19983:15;;;19975:56;1056:36109;;19983:19;;19975:56;:::i;:::-;20045:9;20041:378;;2569:103:5;20567:21:1;20506:33;20453:29;:11;;:29;:::i;:::-;1056:36109;;;;20506:33;;:::i;20567:21::-;1056:36109;;20615:10;20673:828;20866:297;20724:30;:11;;1056:36109;;-1:-1:-1;1083:40:16;992:138;;20724:30:1;1056:36109;;;20935:51;;;;;20962:4;20935:51;;21024:125;21069:26;:11;;:26;:::i;:::-;1056:36109;;;:::i;:::-;;;;-1:-1:-1;;;;;1056:36109:1;21024:125;;;1056:36109;;20866:297;1056:36109;;;;21233:258;;;21289:4;;21364:23;:11;;:23;:::i;:::-;21350:37;;20673:828;;21233:258;21511:75;21426:27;;21532:23;21426:27;21471:5;21532:23;1056:36109;21519:36;;;21511:75;:::i;20935:51::-;21024:125;20970:16;;1056:36109;-1:-1:-1;;;;;1056:36109:1;20935:51;;;20041:378;20074:76;1056:36109;;20045:9;20082:28;;20074:76;:::i;:::-;20200:27;1056:36109;;20045:9;20200:27;:::i;:::-;20245:10;20241:168;;20041:378;;;;20241:168;-1:-1:-1;20300:10:1;;;20351:43;20300:10;;20292:43;;;;:::i;20351:::-;20241:168;;;2569:103:5;;;:::i;:::-;1698:72:4;;:::i;:::-;3069:59:1;28694:15;;;1056:36109;3077:15;:27;;3069:59;:::i;:::-;-1:-1:-1;28757:22:1;;;1056:36109;28749:67;1056:36109;;28757:26;;28749:67;:::i;:::-;28830:9;:13;;28826:118;;;;2569:103:5;28995:12:1;;;:30;:12;;:30;:::i;:::-;28955:70;;29059:12;;;;;:30;:12;;:30;:::i;:::-;29115:13;;;;29104:34;29115:16;:13;;:16;:::i;29104:34::-;:72;;;2569:103:5;29100:3247:1;;;-1:-1:-1;;;29277:15:1;;;1056:36109;;29277:15;;;29252:61;;1056:36109;;29277:15;;-1:-1:-1;;;;;1056:36109:1;29252:61;:::i;:::-;29376:15;;;;1056:36109;;;;;;;;;;;;;;;;29351:62;;;;:::i;:::-;29452:16;;;:::i;:::-;29482:20;;;;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;29516:19;;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;;;-1:-1:-1;;;;;1056:36109:1;29621:16;;;;1056:36109;29574:71;;;:::i;:::-;29685:16;;;:::i;:::-;29715:18;;;;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;29747:20;;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;;;;29853:11;;;;:::i;:::-;1056:36109;29806:66;;;:::i;:::-;29897:11;;;;;:::i;:::-;1056:36109;29938:4;1056:36109;;;;;;;-1:-1:-1;;;;;1056:36109:1;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;29927:15;29923:175;29938:4;;32372:26;29938:4;30222:15;29938:4;32408:78;29938:4;1056:36109;29938:4;1056:36109;29938:4;30204:16;29938:4;30150:15;29938:4;1056:36109;29938:4;;;30004:8;29983:4;;30004:8;;:::i;1056:36109::-;30150:15;;:::i;:::-;30204:16;1056:36109;-1:-1:-1;;;;;1056:36109:1;;;32372:26;32416:14;;;;;:::i;32408:78::-;32497:279;;29100:3247;2634:1:5;;;1787;3171:21;1056:36109:1;2991:208:5;32497:279:1;32542:26;28830:9;32542:20;28830:9;;32542:20;:::i;:26::-;32604:10;32600:166;32497:279;32600:166;-1:-1:-1;32659:10:1;;;32710:43;32659:10;;32651:43;;;;:::i;32710:::-;32600:166;32497:279;;29923:175;30089:8;30063:10;;30089:8;;:::i;:::-;29923:175;;29100:3247;30260:34;30271:16;:13;;;;;;;;:16;:::i;30260:34::-;:72;;;29100:3247;30256:2091;;;30527:12;;;;;:30;;;:::i;:::-;-1:-1:-1;;;30620:15:1;;;1056:36109;;30620:15;;;30595:61;;1056:36109;;30620:15;;-1:-1:-1;;;;;1056:36109:1;30595:61;:::i;:::-;30695:16;;;:::i;:::-;30725:18;;;;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;30757:20;;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;;;-1:-1:-1;;;;;1056:36109:1;30863:16;;;1056:36109;;;;30816:71;;;:::i;:::-;30912:11;;;;:::i;:::-;1056:36109;30952:4;1056:36109;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;-1:-1:-1;;;;;1056:36109:1;32408:78;;32372:26;;31425:89;;31213:198;;31165:15;;30952:4;;;;1056:36109;;-1:-1:-1;;;;;1056:36109:1;;30941:15;30952:4;;31018:8;;30997:4;;31018:8;:::i;1056:36109::-;31158:4;;31165:15;;:::i;:::-;31250:16;;;1056:36109;31284:16;;;;1056:36109;-1:-1:-1;;;;;1056:36109:1;31361:12;;1056:36109;;;:::i;:::-;;;;31158:4;28995:12;31337:60;;1056:36109;31213:198;:::i;:::-;1056:36109;;31433:29;31425:89;:::i;30937:175::-;31103:8;;31077:10;;31103:8;:::i;30256:2091::-;31547:13;;;;;;;31536:34;31547:16;:13;;:16;:::i;31536:34::-;:72;;;30256:2091;31532:815;;30256:2091;;;;32372:26;30256:2091;32408:78;30256:2091;19027:33;:::i;31532:815::-;32302:16;31649:12;;32408:78;31649:12;;;32320:15;31649:12;:30;32372:26;31649:12;;;:30;:::i;:::-;31625:54;31719:16;1056:36109;;32080:184;31840:62;31719:16;;:::i;:::-;31750:20;;;;;;:::i;:::-;31784:19;;;;;:::i;:::-;31865:15;;;1056:36109;;31865:15;;1056:36109;-1:-1:-1;;;;;1056:36109:1;24162:61;:::i;31840:62::-;1056:36109;;;;;31941:71;;1056:36109;;-1:-1:-1;;;;;1056:36109:1;31988:16;;;1056:36109;31941:71;;:::i;:::-;32043:11;;;;:::i;:::-;1056:36109;32217:12;;1056:36109;;;:::i;:::-;;;;32238:10;28995:12;32193:57;;1056:36109;31213:198;:::i;32080:184::-;32302:16;;;;1056:36109;;;;;;;;;32320:15;31532:815;;;31536:72;31585:13;31574:34;31585:16;:13;;:16;:::i;31574:34::-;31536:72;;30260;30309:13;30298:34;30309:16;:13;;:16;:::i;30298:34::-;30260:72;;29104;29153:13;29142:34;29153:16;:13;;:16;:::i;29142:34::-;29104:72;;28826:118;28857:87;1056:36109;;28830:9;28865:35;;28857:87;:::i;:::-;28826:118;;1056:36109;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;3187:515;;3639:12;3187:515;;3579:18;3187:515;;6268:76:3;;:::i;:::-;;;:::i;:::-;1573:12:2;3394:10:1;1573:12:2;:::i;:::-;6268:76:3;;:::i;:::-;;;:::i;:::-;1787:1:5;3171:21;1056:36109:1;6268:76:3;;:::i;:::-;;;:::i;:::-;1490:15:4;1056:36109:1;;-1:-1:-1;;1056:36109:1;;;3477:22;1056:36109;;-1:-1:-1;;;;;;1056:36109:1;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;3509:22;1056:36109;;;;;;;;;;;;;;3541:28;1056:36109;;;;;;;;;;;;;-1:-1:-1;1056:36109:1;;3579:18;3607:22;3624:5;3607:22;1056:36109;;3607:22;1056:36109;;;;;;-1:-1:-1;;;;;1056:36109:1;;3639:12;1056:36109;;;3639:12;1056:36109;;3639:12;-1:-1:-1;;1056:36109:1;;:::o;2569:103:5:-;22139:56:1;2569:103:5;;;:::i;:::-;1698:72:4;;:::i;:::-;3069:59:1;21770:15;;;1056:36109;3077:15;:27;;3069:59;:::i;:::-;21833:22;;;1056:36109;21825:67;1056:36109;;21833:26;;21825:67;:::i;:::-;22310:78;22266:33;21906:9;:13;;21902:118;;;;2569:103:5;22064:16:1;;;1056:36109;22094:16;;;1056:36109;22031:174;;1056:36109;-1:-1:-1;;;;;1056:36109:1;22163:11;;1056:36109;;;:::i;:::-;;;;22183:10;22139:56;;;1056:36109;31213:198;:::i;22031:174::-;-1:-1:-1;;1056:36109:1;22274:14;;1056:36109;;;-1:-1:-1;;;;;1056:36109:1;19027:33;:::i;22310:78::-;22399:294;;2569:103:5;-1:-1:-1;;;1056:36109:1;;22703:34;1056:36109;22399:294;22471:26;21906:9;22471:20;21906:9;;22471:20;:::i;:26::-;22515:10;22511:172;22399:294;22511:172;-1:-1:-1;22183:10:1;;;22625:43;22183:10;;22564:43;;;;:::i;22625:::-;22511:172;22399:294;;21902:118;21933:87;1056:36109;;21906:9;21941:35;;21933:87;:::i;:::-;21902:118;;1056:36109;;;;:::o;:::-;;;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;:::o;15105:1296::-;;15407:37;15541:68;15105:1296;;;;15281:1;15266:16;;;;:36;;;;15105:1296;15258:45;;;:::i;:::-;15407:37;;;;:::i;:::-;15504:9;:27;:9;;:27;:::i;:::-;15575:9;1056:36109;;;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;15541:68;:::i;:::-;-1:-1:-1;15675:140:1;;;-1:-1:-1;;;;;;1056:36109:1;;;;;;15711:18;15675:140;15825:570;;;-1:-1:-1;15870:10:1;;;;;1056:36109;15894:11;;-1:-1:-1;;;;;;1056:36109:1;;15882:10;15894:11;;:::i;15825:570::-;15993:9;;:28;:9;;1056:36109;;-1:-1:-1;1083:40:16;992:138;;15993:28:1;:9;;;16053;;16092:53;16053:9;:21;:9;;:21;:::i;:::-;16041:33;;16125:10;16092:53;;:::i;:::-;;15105:1296::o;15989:396::-;1056:36109;16334:10;16358:11;1056:36109;;15281:1;1056:36109;16334:10;1056:36109;;;;;;;;;15675:140;1056:36109;-1:-1:-1;;;;;;1056:36109:1;;;;;;15773:18;15675:140;;15266:36;-1:-1:-1;15281:1:1;15286:16;;15266:36;;2678:307:5;1829:1;2805:7;1056:36109:1;2805:18:5;2801:86;;1829:1;2805:7;1056:36109:1;2678:307:5:o;2801:86::-;2846:30;;;-1:-1:-1;2846:30:5;;-1:-1:-1;2846:30:5;2261:128:4;1056:36109:1;2179:7:4;1056:36109:1;;2322:61:4;;2261:128::o;2322:61::-;2357:15;;;-1:-1:-1;2357:15:4;;-1:-1:-1;2357:15:4;1779:314:16;;3572:62:14;3527:2;1056:36109:1;;3580:28:14;;3572:62;:::i;:::-;3674:119;;;;;;1056:36109:1;;;;3998:27:14;1056:36109:1;;;4086:81:14;;;;1056:36109:1;;3572:62:14;1056:36109:1;;3674:119:14;1056:36109:1;;3580:28:14;;3572:62;:::i;:::-;3674:119;;;;;1779:314:16;:::o;1056:36109:1:-;;;-1:-1:-1;;;1056:36109:1;;3674:119:14;1056:36109:1;;;;3527:2:14;1056:36109:1;;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;3724:642;3831:10;1056:36109;;;;3816:14;1056:36109;;;;;;3724:642;;;1056:36109;;3812:52;;3889:21;:41;1056:36109;3902:7;1056:36109;3889:21;;:::i;:::-;3915:14;1056:36109;3889:41;;:::i;:::-;1056:36109;-1:-1:-1;;;;;1056:36109:1;3947:21;;:40;;;;3724:642;3945:75;;;3724:642;3941:317;;;4114:41;1056:36109;;;;;;4064:12;1056:36109;;;;;;;;;;4056:44;;;;:::i;:::-;;4114:41;:::i;:::-;1056:36109;;;;;;4321:15;1056:36109;;;;3831:10;;;4282:55;;;3724:642;:::o;3941:317::-;4240:12;1056:36109;4254:3;;1056:36109;;-1:-1:-1;;;;;1056:36109:1;3831:10;4254:3;;:::i;:::-;3941:317;;3945:75;3993:21;;;:27;3945:75;;3947:40;-1:-1:-1;3983:4:1;1056:36109;3972:15;;-1:-1:-1;;;;;1056:36109:1;;;3972:15;;;3947:40;;3812:52;3856:8;;1056:36109;3856:8;:::o;805:10:19:-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;1056:36109:1;805:10:19;;1056:36109:1;;805:10:19:o;:::-;;;;;;;;;;;;;;;;;:::o;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;;;;805:10:19;;;1056:36109:1;805:10:19;;;1056:36109:1;;;;;;805:10:19;;;1056:36109:1;805:10:19;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;805:10:19;;;;;;;:::o;33123:934:1:-;33639:36;;33123:934;1056:36109;;-1:-1:-1;;;;;1056:36109:1;;33396:23;33392:54;;33123:934;33639:31;1056:36109;33748:19;33507:27;:9;;:27;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;;33563:18;;;;1056:36109;;;;;33639:31;:::i;:36::-;33748:19;;:::i;:::-;33785:157;33831:70;;;;;33639:351;33960:16;;805:10:19;33831:70:1;;1056:36109;;33960:16;;;;;;;:::i;:::-;;1056:36109;;33960:16;;;;;;:::i;:::-;1056:36109;;-1:-1:-1;;;33639:351:1;;1056:36109;;;;;;;33639:351;;;;:::i;:::-;;;;;;;;;;34016:33;33639:351;1056:36109;;;33639:351;;;33831:70;-1:-1:-1;34018:30:1;;;;34016:33;:::i;34018:30::-;;;34016:33;:::i;33639:351::-;;;;;;;1056:36109;33639:351;1056:36109;33639:351;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;33831:70;33639:351;33960:16;;985:49:19;33831:70:1;;;33392:54;33441:4;;-1:-1:-1;33392:54:1;;33123:934;33639:36;;33123:934;1056:36109;;33123:934;;;-1:-1:-1;;;;;1056:36109:1;;33396:23;33392:54;;33123:934;33417:1;33639:31;33507:9;33748:19;33507:27;:9;;:27;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;;33563:18;;;;1056:36109;;;;;33639:31;:::i;:36::-;33748:19;;:::i;:::-;33785:157;-1:-1:-1;;;;;1056:36109:1;;33785:22;1056:36109;;;;33831:70;;;;;;33639:351;33960:16;;805:10:19;33831:70:1;33785:157;1056:36109;;33960:16;;;;;;;:::i;33831:70::-;33639:351;33960:16;;985:49:19;33831:70:1;;33785:157;33960:16;;33639:351;33785:157;;;;33392:54;-1:-1:-1;33441:4:1;33392:54;;731:1078:20;;879:26;731:1078;879:26;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;938:42:20;919:62;938:42;;1056:36109:1;;-1:-1:-1;;;;;;1056:36109:1;;;;;;1122:32:20;;;1056:36109:1;;;;;;;;;;;;;;1022:256:20;;;;1122:32;;1056:36109:1;;;;1022:256:20;1056:36109:1;1122:32:20;1056:36109:1;1112:43:20;;1056:36109:1;;-1:-1:-1;;;;;;1122:32:20;1022:256;;1056:36109:1;;;;;;;;-1:-1:-1;;;;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;;1022:256:20;1056:36109:1;1012:267:20;;1291:89;1056:36109:1;1291:89:20;915:888;731:1078::o;915:888::-;1056:36109:1;;-1:-1:-1;;;;;;1056:36109:1;;;;;;1535:32:20;;;1056:36109:1;;;;;;;;;;;;;;1435:256:20;;;;1535:32;;1056:36109:1;;;;1435:256:20;1056:36109:1;1535:32:20;1056:36109:1;1525:43:20;;1056:36109:1;;-1:-1:-1;;;;;;1535:32:20;1435:256;;1056:36109:1;;;;;;;;-1:-1:-1;;;;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;3970:503:20:-;;;;4104:59;4127:1;1056:36109:1;;4112:16:20;;4104:59;:::i;:::-;4183:23;1056:36109:1;;4183:23:20;:::i;:::-;1056:36109:1;;;;;;;;;;4224:1:20;4281:3;1056:36109:1;;-1:-1:-1;;1056:36109:1;;;;;;;4260:19:20;;;;;4357:7;4409:47;4336:42;4357:7;;4278:1;4357:7;;;:::i;:::-;4366:11;;4371:5;;;:::i;:::-;4366:11;;:::i;:::-;4336:42;;;:::i;:::-;4422:10;;;;;:::i;:::-;1056:36109:1;4409:47:20;:::i;:::-;4392:64;4400:5;;;:::i;4392:64::-;1056:36109:1;;4252:6:20;;4260:19;;;;3970:503::o;10487:1244:1:-;;;;-1:-1:-1;10646:3:1;10629:15;1056:36109;;10629:15;:::i;:::-;10625:19;;;;;10700:7;;;;;:::i;:::-;10714:5;10709:11;;10714:5;;;:::i;10709:11::-;10755:42;;;;;:::i;:::-;10848:49;11065:16;10833:65;10848:49;;;;;:::i;11065:16::-;1056:36109;;;;;;;11065:18;;;;;;;;;;;;;;-1:-1:-1;;;11065:18:1;;;10646:3;-1:-1:-1;;;;;;1056:36109:1;;;;;;;11143:15;;;-1:-1:-1;;;;;1056:36109:1;;;;;11143:61;;;;;1056:36109;;-1:-1:-1;;;11236:49:1;;-1:-1:-1;;;;;1056:36109:1;;11065:18;11236:49;;1056:36109;;11236:49;;1056:36109;;;;;;11236:49;;;;;;;:67;:49;11336:71;11236:49;-1:-1:-1;11236:49:1;;;:67;;:::i;11336:71::-;11472:67;;;;-1:-1:-1;11472:67:1;;;11570:15;1056:36109;;11570:15;:::i;:::-;11566:19;;:83;;;11588:55;11636:5;11631:11;;11636:5;;;:::i;:::-;11631:11;;:::i;:::-;11588:55;;;:::i;:::-;11566:83;;11701:12;;:::i;:::-;11663:51;;;;;;-1:-1:-1;1056:36109:1;;11663:51;1056:36109;;;;;;;;;;;;11663:51;;11065:18;11663:51;;;:::i;:::-;;;;;;;;;;10643:1;11663:51;;;11566:83;10646:3;1056:36109;10617:6;;11663:51;;;-1:-1:-1;11663:51:1;;;:::i;:::-;;;;11566:83;;;;;;11472:67;-1:-1:-1;11472:67:1;;;11236:49;;;;;;;;;;;;;;:::i;11143:61::-;;;;11065:18;-1:-1:-1;;;;;11065:18:1;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;10625:19;;;;;;10487:1244::o;320:127:21:-;;1056:36109:1;;;;;;;;320:127:21:o;1056:36109:1:-;;;;;;;;;;;;;:::i;35447:699::-;35594:4;1056:36109;35447:699;;;;;35585:13;;-1:-1:-1;;;;;1056:36109:1;;;35585:13;-1:-1:-1;;;;;1056:36109:1;;;;35585:13;;;:47;;35447:699;35581:559;;;-1:-1:-1;35594:4:1;1056:36109;;;-1:-1:-1;1056:36109:1;35677:19;;:11;;-1:-1:-1;;;;;1056:36109:1;35677:11;1056:36109;35677:19;:35;;;;;;1056:36109;;35594:4;1056:36109;;;;;;;;;35677:35;;;;;;;;;35761:38;35677:35;35761:38;35677:35;;;35581:559;-1:-1:-1;35594:4:1;1056:36109;35761:20;;:11;;-1:-1:-1;;;;;1056:36109:1;35761:11;1056:36109;35761:20;1056:36109;;-1:-1:-1;;;35761:38:1;;-1:-1:-1;;;;;1056:36109:1;;;35594:4;35761:38;;1056:36109;;;;;;;;;;;;;;35677:35;;1056:36109;;;;;;;35761:38;;;;;;;;;;;35581:559;35447:699::o;35761:38::-;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;35677:35;;;;;;;:::i;:::-;;;;35581:559;-1:-1:-1;;;;;1056:36109:1;;35837:4;35820:22;35837:4;;35998:5;;;;:::i;35816:324::-;36123:5;;;:::i;35585:47::-;35602:21;;;:30;;35585:47;;772:274:17;;1056:36109:1;772:274:17;-1:-1:-1;1056:36109:1;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;919:15:17;915:56;;772:274;1056:36109:1;;;;;;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;;;988:51:17;;1056:36109:1;;;988:51:17;;1056:36109:1;;772:274:17:o;915:56::-;;;;1293:592;1056:36109:1;;1422:10:17;;;1056:36109:1;1293:592:17;;;-1:-1:-1;;;;;1056:36109:1;;;;;;1409:23:17;1056:36109:1;;;1508:229:17;;;;-1:-1:-1;;;;;1056:36109:1;;;;1626:43:17;;1056:36109:1;;1661:7:17;;1056:36109:1;1661:7:17;;1056:36109:1;;;;;;1661:7:17;1056:36109:1;;-1:-1:-1;;;;;1056:36109:1;;;1422:10:17;1626:43;;1056:36109:1;;;;;;;;;;;;;;;;;;;;;1626:43:17;1056:36109:1;1626:43:17;1056:36109:1;1616:54:17;;1661:7;1056:36109:1;-1:-1:-1;;;;;;1422:10:17;1508:229;;1056:36109:1;;;;;;;;-1:-1:-1;;;;;;1056:36109:1;;;;;229:66:17;;;1056:36109:1;;;;229:66:17;;;;1056:36109:1;;;;229:66:17;;;;;1977:162:2;1891:6;1056:36109:1;-1:-1:-1;;;;;1056:36109:1;930:10:10;2036:23:2;2032:101;;1977:162::o;2032:101::-;2082:40;;;-1:-1:-1;2082:40:2;930:10:10;2082:40:2;1056:36109:1;;-1:-1:-1;2082:40:2;1397:171:8;1056:36109:1;;-1:-1:-1;;;1517:43:8;;;;-1:-1:-1;;;;;1056:36109:1;;;1517:43:8;;;1056:36109:1;;;;;;;;1517:43:8;;;1056:36109:1;;;;1517:43:8;1056:36109:1;1517:43:8;;:::i;1056:36109:1:-;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;2797:510:20;;;;2924:12;;1056:36109:1;;3155:31:20;3111:17;3215:19;3002:13;;;;:31;;;2797:510;2994:84;;;:::i;:::-;3111:17;:::i;:::-;3155:31;;;:::i;:::-;3215:19;;:::i;:::-;:40;1056:36109:1;;;;;;;;266:16:21;;1056:36109:1;;3277:23:20;;;:::i;1056:36109:1:-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;3002:31:20;-1:-1:-1;3019:14:20;;;3002:31;;1056:36109:1;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;3093:187:2;3185:6;1056:36109:1;;-1:-1:-1;;;;;1056:36109:1;;;-1:-1:-1;;;;;;1056:36109:1;;;;;;;;;;3233:40:2;-1:-1:-1;;3233:40:2;3093:187::o;3425:466:20:-;;3551:13;;1056:36109:1;;3734:24:20;3631:13;;3734:34;3631:13;;;:31;;;3425:466;3623:84;;;:::i;:::-;3734:24;:::i;:::-;:34;:::i;:::-;3797:25;1056:36109:1;;;;;;;3853:23:20;;3797:34;;;:::i;:::-;3853:23;;:::i;:::-;3882:1;1056:36109:1;;;;;;;;266:16:21;;1056:36109:1;;3425:466:20;:::o;3631:31::-;-1:-1:-1;3648:14:20;;;3631:31;;1056:36109:1;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;2319:127:16;1056:36109:1;2414:25:16;545:50:14;553:12;;;;:::i;:::-;:23;;545:50;:::i;:::-;613:16;;-1:-1:-1;613:16:14;:::i;:::-;;605:53;613:26;605:53;:::i;:::-;668:63;1056:36109:1;;693:16:14;;-1:-1:-1;693:16:14;:::i;:::-;-1:-1:-1;676:33:14;668:63;:::i;:::-;775:2598;;;;;;;-1:-1:-1;775:2598:14;;;;;;;2319:127:16;:::o;775:2598:14:-;;;;563:2;775:2598;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;775:2598:14;;563:2;775:2598;-1:-1:-1;;775:2598:14;;;;2319:127:16:o;775:2598:14:-;;;;;;;;;;;;;;;;2635:149:16;1056:36109:1;;-1:-1:-1;;1056:36109:1;;;;;;;545:50:14;553:12;;;;:::i;545:50::-;605:53;1056:36109:1;613:16:14;;;;:::i;605:53::-;668:63;1056:36109:1;;693:16:14;;1056:36109:1;693:16:14;:::i;668:63::-;775:2598;;;;;;;;-1:-1:-1;775:2598:14;;;;;;;2635:149:16;:::o;775:2598:14:-;;;;1056:36109:1;563:2:14;775:2598;;;;;;;;;;;;1056:36109:1;;;775:2598:14;;;;;;;;;;;;;;;-1:-1:-1;;775:2598:14;;563:2;775:2598;-1:-1:-1;;775:2598:14;;;;2635:149:16:o;775:2598:14:-;;;;;;;;;;;;;;;;4551:524:20;;;;;4685:59;4708:1;1056:36109:1;;4693:16:20;;4685:59;:::i;:::-;4764:23;1056:36109:1;;4764:23:20;:::i;:::-;1056:36109:1;;;;;;;;;;;;4797:39:20;;;;:::i;:::-;1056:36109:1;;;-1:-1:-1;;1056:36109:1;;;;;;;4846:223:20;4877:5;;;4551:524;;;:::o;4884:3::-;5012:46;4939:42;4960:11;;4965:5;;;:::i;:::-;4960:11;;:::i;:::-;4973:7;;;;;:::i;:::-;4939:42;;;:::i;:::-;5024:10;;;;;:::i;:::-;1056:36109:1;5012:46:20;:::i;:::-;4995:63;5003:5;;;:::i;4995:63::-;1056:36109:1;;;;;-1:-1:-1;;1056:36109:1;;4851:24:20;;34107:1334:1;;;;;-1:-1:-1;;;;;1056:36109:1;;34381:23;34377:54;;34107:1334;1056:36109;34634:31;34492:9;34634:36;34492:27;:9;;:27;:::i;:::-;-1:-1:-1;;;;;1056:36109:1;;;;;;34548:18;;1056:36109;;;34634:31;:::i;:36::-;34744:20;1056:36109;34743:21;34744:20;;;:::i;:::-;34743:21;:::i;:::-;34782:157;34828:70;;;;;34634:353;34957:16;;805:10:19;34828:70:1;1056:36109;;34957:16;;;;;;;:::i;:::-;1056:36109;;-1:-1:-1;;;34634:353:1;;1056:36109;;;;;;;34634:353;;;;:::i;:::-;;;;;;;;;;1056:36109;;;34634:353;;;34828:70;-1:-1:-1;35065:134:1;;;35122:13;;35395:39;35122:13;;:::i;:::-;35065:134;;35403:30;;35395:39;:::i;35065:134::-;35184:13;;;35395:39;35184:13;;:::i;:::-;35065:134;;;34634:353;;;;;;;1056:36109;34634:353;1056:36109;34634:353;;;;;;;:::i;:::-;;;;;;34828:70;34634:353;34957:16;;985:49:19;34828:70:1;;;34377:54;-1:-1:-1;34426:4:1;34377:54;;34107:1334;;;;;;-1:-1:-1;;;;;1056:36109:1;;34381:23;34377:54;;34107:1334;1056:36109;34634:31;34492:9;34634:36;34492:27;:9;;:27;:::i;34634:36::-;34744:20;34402:1;34743:21;34744:20;;;:::i;34743:21::-;-1:-1:-1;;;;;1056:36109:1;;34782:22;;1056:36109;;;34782:157;;;;;34828:70;;;;;;34634:353;34957:16;;805:10:19;34828:70:1;34782:157;1056:36109;;34957:16;;;;;;;:::i;:::-;1056:36109;;-1:-1:-1;;;34634:353:1;;1056:36109;;;;;;;34634:353;;;;:::i;:::-;;;;;;;;;;34402:1;;;34634:353;;;34782:157;-1:-1:-1;35065:134:1;;;35122:13;;;:::i;:::-;35065:134;;35367:67;;;34107:1334;;:::o;35367:67::-;35395:39;35403:30;;35395:39;:::i;35065:134::-;35184:13;;;;:::i;:::-;35065:134;;;34634:353;;;;;;;1056:36109;34634:353;1056:36109;34634:353;;;;;;;:::i;:::-;;;;;;34828:70;34634:353;34957:16;;985:49:19;34828:70:1;;34782:157;34957:16;;34634:353;34782:157;;;;34377:54;-1:-1:-1;34426:4:1;34377:54;;9600:744;;;;;-1:-1:-1;9753:3:1;9736:15;1056:36109;;9736:15;:::i;:::-;9732:19;;;;;9807:7;;;;;:::i;:::-;9821:5;9816:11;;9821:5;;;:::i;:::-;9816:11;;:::i;:::-;9862:42;;;;;:::i;:::-;9943:5;;9935:14;9943:5;;;:::i;9935:14::-;1056:36109;;-1:-1:-1;;;;;1056:36109:1;;;;;10000:15;1056:36109;;10185:70;:65;10200:49;-1:-1:-1;10000:61:1;;;10092:15;1056:36109;;10092:15;:::i;:::-;10088:19;;:83;;;10110:55;10153:11;;10158:5;;;:::i;:::-;10153:11;;:::i;:::-;10110:55;;;:::i;:::-;10088:83;;10200:49;;:::i;10185:70::-;10301:12;;:::i;:::-;10185:142;;;;;;-1:-1:-1;1056:36109:1;;10185:142;1056:36109;;;;;;;;;;;;10185:142;;;;;;:::i;:::-;;;;;;;;;;9750:1;10185:142;;;10088:83;9753:3;1056:36109;9724:6;;10185:142;;;-1:-1:-1;10185:142:1;;;:::i;:::-;;;;10088:83;;;;;10000:61;10185:70;:65;10200:49;-1:-1:-1;10000:61:1;;;9732:19;;;;;;;9600:744::o;648:259:15:-;-1:-1:-1;;;;;1056:36109:1;1335:44:15;;648:259;;856:43;;648:259;856:43;:::i;1335:44::-;1056:36109:1;1398:10:15;;:27;1056:36109:1;;648:259:15;:::o;1056:36109:1:-;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;453:140:21;;3124:3:20;1056:36109:1;;;;;;3124:3:20;1056:36109:1;;;;;;;3124:3:20;542:9:21;1056:36109:1;541:20:21;1056:36109:1;;453:140:21:o;1056:36109:1:-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;453:140:21;;3229:4:20;1056:36109:1;;;;;;3229:4:20;1056:36109:1;;;;;;;3229:4:20;542:9:21;1056:36109:1;541:20:21;1056:36109:1;;453:140:21:o;:::-;1056:36109:1;;453:140:21;531:6;;;:30;;;;453:140;1056:36109:1;;;;;453:140:21:o;531:30::-;1056:36109:1;;;;-1:-1:-1;1056:36109:1;-1:-1:-1;1056:36109:1;;;;;;;;;;;541:15:21;542:9;;541:15;:::i;:::-;:20;531:30;;;;599:278;;674:5;;1056:36109:1;;865:5:21;;;:::i;1056:36109:1:-;;;;678:1:21;1056:36109:1;;;;;678:1:21;1056:36109:1;1807:199:8;1056:36109:1;;-1:-1:-1;;;1945:53:8;;;;-1:-1:-1;;;;;1056:36109:1;;;1945:53:8;;;1056:36109:1;;;;;;;;;;;;;;;;;1945:53:8;;;;;;;1056:36109:1;1945:53:8;:::i;912:121:18:-;-1:-1:-1;;;992:10:18;;1056:36109:1;;;912:121:18;:::o;297:345:20:-;;;;-1:-1:-1;;;;;1056:36109:1;;;;;;422:16:20;;;1056:36109:1;;509:15:20;;;;:53;;490:72;-1:-1:-1;;;;;1056:36109:1;;580:20:20;1056:36109:1;;297:345:20:o;1056:36109:1:-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;;;;509:53:20;;;1056:36109:1;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;1864:387:20;;2087:62;;1864:387;2102:32;2017:26;;;;:::i;:::-;-1:-1:-1;1056:36109:1;-1:-1:-1;;;;;1056:36109:1;;;2102:32:20;:::i;:::-;1056:36109:1;;;;;;;;;;2087:62:20;;;;;;;;;-1:-1:-1;;;2087:62:20;;;1864:387;-1:-1:-1;;;;;;1056:36109:1;;;;;;;-1:-1:-1;;;;;1056:36109:1;;;;;2182:16:20;1056:36109:1;;1864:387:20;:::o;2182:62::-;2159:85;1864:387;:::o;2087:62::-;-1:-1:-1;;;;;2087:62:20;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;4874:640:8;2858:1:9;4874:640:8;3521:55:9;4874:640:8;1056:36109:1;;;;;;3473:31:9;;;;;;;;;;;;:::i;:::-;3521:55;;;:::i;:::-;1056:36109:1;;5377:22:8;;;;:57;;;;4874:640;5373:135;;;;4874:640;:::o;5373:135::-;5457:40;;;2858:1:9;5457:40:8;;1056:36109:1;;2858:1:9;5457:40:8;5377:57;5404:30;;;3473:31:9;5404:30:8;;;;;;;;:::i;:::-;5403:31;5377:57;;;;1056:36109:1;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;1056:36109:1;;;;;;;;;;;;-1:-1:-1;;;1056:36109:1;;;;;;;6459:141:3;1056:36109:1;-1:-1:-1;;;;;;;;;;;1056:36109:1;;;;6525:18:3;6521:73;;6459:141::o;6521:73::-;6566:17;;;-1:-1:-1;6566:17:3;;-1:-1:-1;6566:17:3;4636:582:9;;4808:8;;-1:-1:-1;1056:36109:1;;5885:21:9;:17;;6057:142;;;;;;5881:383;6236:17;;;5905:1;6236:17;;5905:1;6236:17;4804:408;1056:36109:1;;5056:22:9;:49;;;4804:408;5052:119;;5184:17;;:::o;5052:119::-;-1:-1:-1;;;5077:1:9;5132:24;;;-1:-1:-1;;;;;1056:36109:1;;;;5132:24:9;1056:36109:1;;;5132:24:9;5056:49;5082:18;;;:23;5056:49;

Swarm Source

ipfs://28da49c44c096942378115c02739e31f194dda1faaef8e389be874d6c214dea4

Block Transaction Difficulty 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
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.