false
true
0

Contract Address Details

0xC24c1A4746dFF75A25835906BfFF5573a731e151

Contract Name
HeroABLE
Creator
0x5f1d1a–4e7dba at 0x4a27ab–105462
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
769 Transactions
Transfers
0 Transfers
Gas Used
0
Last Balance Update
25981727
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
HeroABLE




Optimization enabled
true
Compiler version
v0.8.27+commit.40a35a09




Optimization runs
200
EVM Version
default




Verified at
2025-11-27T06:06:22.104242Z

Contract source code

// SPDX-License-Identifier: MIT
// File: @uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol

pragma solidity >=0.6.2;

interface IUniswapV2Router01 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountETH);
    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETHWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountToken, uint amountETH);
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);
    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);

    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}

// File: @uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol

pragma solidity >=0.6.2;


interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountETH);
    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}

// File: @uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol

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: @openzeppelin/contracts/token/ERC20/IERC20.sol


// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

// File: @openzeppelin/contracts/utils/Context.sol


// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @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 Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

// File: @openzeppelin/contracts/access/Ownable.sol


// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;


/**
 * @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.
 *
 * By default, the owner account will be the one that deploys the contract. 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 Ownable is Context {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @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 {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @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 {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _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);
    }
}

// File: contracts/Pulsechain/HeroABLE.sol


pragma solidity ^0.8.26;





contract HeroABLE is Ownable {
    struct Pair {
        address tokenA;
        address tokenB;
        address router;
        address pairAddress;
        uint256 heroForLp;
        uint256 totalHeroLpAdded;
    }

    Pair[] public pairs;

    uint256 public heroGained;
    address public rewardsAddress;
    address public burnAddress = 0x0000000000000000000000000000000000000000;
    address public heroToken = 0x35a51Dfc82032682E4Bda8AAcA87B9Bc386C3D27;
    IERC20 public wpls = IERC20(0xA1077a294dDE1B09bB078844df40758a5D0f9a27);
    uint256 public lpAddThreshold = 10000e18;
    uint256 public distributeThreshold = 10000e18;
    uint256 public minGain = 300e18;
    bool public targetedLpMode = false;
    address[] public targetLpPairs;

    uint256 public rewardsPercent = 0;
    uint256 public burnPercent = 25;
    uint256 public lpPercent = 50;
    uint256 public gasCompPercent = 25;

    address private signer;

    uint256 public totalHeroBurn;
    uint256 public totalHeroReward;
    uint256 public totalHeroLp;
    uint256 public totalHeroGasComp;
    uint256 public pendingGainsDistribution;

    IUniswapV2Router02 public pulseRouterV1 = IUniswapV2Router02(0x98bf93ebf5c380C0e6Ae8e192A7e2AE08edAcc02);
    IUniswapV2Router02 public pulseRouterV2 = IUniswapV2Router02(0x165C3410fC91EF562C50559f7d2289fEbed552d9);
    IUniswapV2Router02 public nineinchRouter = IUniswapV2Router02(0xeB45a3c4aedd0F47F345fB4c8A1802BB5740d725);

    modifier onlySigner() {
        require(msg.sender == signer, "Not signer");
        _;
    }

    constructor() Ownable() {
        signer = msg.sender;
        rewardsAddress = address(heroToken);

        IERC20(heroToken).approve(address(pulseRouterV1), type(uint256).max);
        IERC20(heroToken).approve(address(pulseRouterV2), type(uint256).max);
        IERC20(heroToken).approve(address(nineinchRouter), type(uint256).max);
    }

    function addPair(
        address tokenA, 
        address tokenB, 
        address router, 
        address pairAddress
    ) external onlyOwner {
        require(tokenA != address(0) && tokenB != address(0), "Invalid token addresses");
        require(router != address(0), "Invalid router address");
        require(pairAddress != address(0), "Invalid pair address");

        require(
            router == address(pulseRouterV1) || 
            router == address(pulseRouterV2) || 
            router == address(nineinchRouter),
            "Router not supported"
        );

        IERC20(tokenA).approve(address(pulseRouterV1), type(uint256).max);
        IERC20(tokenB).approve(address(pulseRouterV1), type(uint256).max);
        IERC20(tokenA).approve(address(pulseRouterV2), type(uint256).max);
        IERC20(tokenB).approve(address(pulseRouterV2), type(uint256).max);
        IERC20(tokenA).approve(address(nineinchRouter), type(uint256).max);
        IERC20(tokenB).approve(address(nineinchRouter), type(uint256).max);

        pairs.push(Pair(tokenA, tokenB, router, pairAddress, 0, 0));

        emit PairAdded(tokenA, tokenB, router, pairAddress);
    }

    function getPairs() external view returns (Pair[] memory) {
        uint256 pairCount = pairs.length;
        Pair[] memory result = new Pair[](pairCount);

        for (uint256 i = 0; i < pairCount; i++) {
            result[i] = pairs[i];
        }

        return result;
    }

    function getLpAddedForPair(address pairAddress) public view returns (uint256) {
        require(pairAddress != address(0), "Invalid pair address");

        for (uint256 i = 0; i < pairs.length; i++) {
            if (pairs[i].pairAddress == pairAddress) {
                return pairs[i].totalHeroLpAdded;
            }
        }

        revert("Pair not found");
    }

    function setRewardsAddress(address _rewardsAddress) external onlyOwner {
        rewardsAddress = _rewardsAddress;
    }

    function setLpAddThreshold(uint256 _newThreshold) external onlyOwner {
        lpAddThreshold = _newThreshold;
    }

    function setTargetLpPairs(address[] calldata lpPairs, bool enabled) external onlyOwner {
        require(lpPairs.length <= 4, "Cannot set more than 4 LP target pairs");
        for (uint256 i = 0; i < lpPairs.length; i++) {
            require(lpPairs[i] != address(0), "Invalid LP target address");
        }
        targetLpPairs = lpPairs;
        targetedLpMode = enabled;

        if (targetedLpMode == true) {
            require(lpPairs.length > 0, "Cannot set more than 4 LP target pairs");
        }
    }

    function setMinGain(uint256 _newMinGain) external onlyOwner {
        minGain = _newMinGain;
    }

    function setSigner(address _signer) external onlyOwner {
        signer = _signer;
    }

    function setDistributionSettings(
        uint256 _rewardsPercent,
        uint256 _burnPercent,
        uint256 _lpPercent,
        uint256 _gasCompPercent,
        uint256 _distributeThreshold
    ) external onlyOwner {
        rewardsPercent = _rewardsPercent;
        burnPercent = _burnPercent;
        lpPercent = _lpPercent;
        gasCompPercent = _gasCompPercent;
        distributeThreshold = _distributeThreshold;
        require(rewardsPercent + burnPercent + lpPercent + gasCompPercent == 100, "Invalid percentages");
        require(gasCompPercent <= 50, "Max 50 percent allowed to gas compensation.");
    }

    function multiSwap(
        address[][] memory swapPaths,
        uint amountIn,
        uint[] memory minAmountsOut
    ) external onlySigner {
        require(swapPaths.length == minAmountsOut.length, "Paths and minAmountsOut mismatch");
        require(swapPaths.length > 1, "At least two swaps required");

        uint256 currentAmount = amountIn;
        uint256[] memory amountsOut = new uint256[](swapPaths.length);
        IUniswapV2Router02[] memory bestRouters = new IUniswapV2Router02[](swapPaths.length);

        address[] memory routers = new address[](3);
        routers[0] = address(pulseRouterV1);
        routers[1] = address(pulseRouterV2);
        routers[2] = address(nineinchRouter);

        for (uint256 i = 0; i < swapPaths.length; i++) {
            require(swapPaths[i].length == 2, "Each swap path must have exactly 2 tokens");

            uint256 bestAmountOut = 0;
            IUniswapV2Router02 bestRouter;

            for (uint256 j = 0; j < routers.length; j++) {
                try IUniswapV2Router02(routers[j]).getAmountsOut(currentAmount, swapPaths[i]) returns (uint[] memory amounts) {
                    uint256 amountOut = amounts[amounts.length - 1];
                    if (amountOut > bestAmountOut) {
                        bestAmountOut = amountOut;
                        bestRouter = IUniswapV2Router02(routers[j]);
                    }
                } catch {
                }
            }

            require(address(bestRouter) != address(0), "No suitable router found for path");

            amountsOut[i] = bestAmountOut;
            bestRouters[i] = bestRouter;
            currentAmount = bestAmountOut;
        }

        require(amountsOut[swapPaths.length - 1] >= amountIn + minGain, "Must gain hero overall.");

        currentAmount = amountIn;
        for (uint256 i = 0; i < swapPaths.length; i++) {
            uint256 tokenBalanceBefore = IERC20(swapPaths[i][swapPaths[i].length - 1]).balanceOf(address(this));

            bestRouters[i].swapExactTokensForTokensSupportingFeeOnTransferTokens(
                currentAmount,
                minAmountsOut[i],
                swapPaths[i],
                address(this),
                block.timestamp
            );

            uint256 tokenBalanceAfter = IERC20(swapPaths[i][swapPaths[i].length - 1]).balanceOf(address(this));
            currentAmount = tokenBalanceAfter - tokenBalanceBefore;
        }
        uint256 finalGain = currentAmount > amountIn ? currentAmount - amountIn : 0;
        heroGained += finalGain;

        _handleLpContributionAndDistribution(finalGain, swapPaths);
    }

    function _handleLpContributionAndDistribution(uint256 finalGain, address[][] memory swapPaths) private {
        uint256 lpContribution;

        if (lpPercent > 0) {
            lpContribution = (finalGain * lpPercent) / 100;
            totalHeroLp += lpContribution;

            if (targetedLpMode && targetLpPairs.length > 0) {
                uint256 lpPerTarget = lpContribution / targetLpPairs.length;
                for (uint256 i = 0; i < targetLpPairs.length; i++) {
                    bool targetFound = false;
                    for (uint256 j = 0; j < pairs.length; j++) {
                        if (pairs[j].pairAddress == targetLpPairs[i]) {
                            pairs[j].heroForLp += lpPerTarget;
                            if (pairs[j].heroForLp >= lpAddThreshold) {
                                _addLiquidity(pairs[j]);
                            }
                            targetFound = true;
                            break;
                        }
                    }
                    require(targetFound, "Target LP pair not found in pairs array");
                }
            } else {
                address finalTokenA = swapPaths[swapPaths.length - 1][0];
                address finalTokenB = swapPaths[swapPaths.length - 1][1];
                for (uint256 i = 0; i < pairs.length; i++) {
                    if (
                        (pairs[i].tokenA == finalTokenA && pairs[i].tokenB == finalTokenB) ||
                        (pairs[i].tokenA == finalTokenB && pairs[i].tokenB == finalTokenA)
                    ) {
                        pairs[i].heroForLp += lpContribution;
                        if (pairs[i].heroForLp >= lpAddThreshold) {
                            _addLiquidity(pairs[i]);
                        }
                        break;
                    }
                }
            }
        }

        pendingGainsDistribution += (finalGain - lpContribution);
        if (pendingGainsDistribution >= distributeThreshold) {
            _distributeGains();
        }
    }

    function _distributeGains() internal {
        uint256 rewardsAmount = (pendingGainsDistribution * rewardsPercent) / (100 - lpPercent);
        uint256 burnAmount = (pendingGainsDistribution * burnPercent) / (100 - lpPercent);
        uint256 gasCompAmount = (pendingGainsDistribution * gasCompPercent) / (100 - lpPercent);

        if (rewardsAmount > 0) {
            IERC20(heroToken).transfer(rewardsAddress, rewardsAmount);
            totalHeroReward += rewardsAmount;
        }

        if (burnAmount > 0) {
            IERC20(heroToken).transfer(burnAddress, burnAmount);
            totalHeroBurn += burnAmount;
        }

        if (gasCompAmount > 0) { 
            address[] memory path = new address[](2);
            path[0] = address(heroToken);
            path[1] = address(wpls);
            pulseRouterV2.swapExactTokensForETHSupportingFeeOnTransferTokens(
                gasCompAmount,
                0,
                path,
                signer,
                block.timestamp
            );
            
            totalHeroGasComp += gasCompAmount;
        }

        pendingGainsDistribution = 0;
    }

    function _addLiquidity(Pair storage pair) internal {
        uint256 heroAmount = pair.heroForLp;
        pair.heroForLp = 0;
        pair.totalHeroLpAdded += heroAmount;

        address router = pair.router;
        address tokenA = pair.tokenA;
        address tokenB = pair.tokenB;

        (, address otherToken) = tokenA == heroToken
            ? (tokenA, tokenB)
            : (tokenB, tokenA);

        uint256 heroBalance = IERC20(heroToken).balanceOf(address(this));

        if (heroAmount > 0 && heroBalance >= heroAmount) {
            uint256 halfHeroAmount = heroAmount / 2;

            address[] memory path = new address[](2);
            path[0] = address(heroToken);
            path[1] = address(otherToken);

            uint256 initialOtherBalance = IERC20(otherToken).balanceOf(address(this));

            IUniswapV2Router02(router).swapExactTokensForTokensSupportingFeeOnTransferTokens(
                halfHeroAmount,
                0,
                path,
                address(this),
                block.timestamp
            );

            uint256 swappedOtherBalance = IERC20(otherToken).balanceOf(address(this)) - initialOtherBalance;

            (uint256 amountA, uint256 amountB, ) = IUniswapV2Router02(router).addLiquidity(
                heroToken,
                otherToken,
                halfHeroAmount,
                swappedOtherBalance,
                0,
                0,
                owner(),
                block.timestamp
            );

            if (halfHeroAmount > amountA) {
                uint256 excessHero = halfHeroAmount - amountA;
                pair.heroForLp += excessHero;
            }

            if (swappedOtherBalance > amountB) {
                uint256 excessOtherToken = swappedOtherBalance - amountB;
                IERC20(otherToken).transfer(owner(), excessOtherToken);
            }
        }
    }

    function withdrawToken(address tokenAddress, uint256 amount) external onlyOwner {
        IERC20(tokenAddress).transfer(owner(), amount);
    }

    function withdrawETH(uint256 amount) external onlyOwner {
        payable(owner()).transfer(amount);
    }

    function getTargetLpPairs() external view returns (address[] memory) {
        return targetLpPairs;
    }

    function getBestAmountsOut(uint256[] memory amountsIn, address[][] memory paths)
        public
        view
        returns (uint256[] memory bestAmountsOut)
    {
        require(amountsIn.length == paths.length, "Amounts and paths length mismatch");

        uint256 numQueries = amountsIn.length;
        bestAmountsOut = new uint256[](numQueries);

        address[] memory routers = new address[](3);
        routers[0] = address(pulseRouterV1);
        routers[1] = address(pulseRouterV2);
        routers[2] = address(nineinchRouter);

        for (uint256 queryIndex = 0; queryIndex < numQueries; queryIndex++) {
            uint256 amountIn = amountsIn[queryIndex];
            address[] memory path = paths[queryIndex];

            uint256 bestAmountOut = 0;

            for (uint256 i = 0; i < routers.length; i++) {
                try IUniswapV2Router02(routers[i]).getAmountsOut(amountIn, path) returns (uint256[] memory amountsOut) {
                    uint256 amountOut = amountsOut[amountsOut.length - 1];
                    if (amountOut > bestAmountOut) {
                        bestAmountOut = amountOut;
                    }
                } catch {
                    continue;
                }
            }

            bestAmountsOut[queryIndex] = bestAmountOut;
        }
    }

    function getReservesForPairs(address[] memory pairAddresses)
        external
        view
        returns (uint256[] memory reserve0s, uint256[] memory reserve1s)
    {
        uint256 pairCount = pairAddresses.length;
        reserve0s = new uint256[](pairCount);
        reserve1s = new uint256[](pairCount);

        for (uint256 i = 0; i < pairCount; i++) {
            address pairAddress = pairAddresses[i];
            require(pairAddress != address(0), "Invalid pair address");

            try IUniswapV2Pair(pairAddress).getReserves() returns (
                uint112 _reserve0,
                uint112 _reserve1,
                uint32
            ) {
                reserve0s[i] = _reserve0;
                reserve1s[i] = _reserve1;
            } catch {
                reserve0s[i] = 0;
                reserve1s[i] = 0;
            }
        }
    }

    receive() external payable {}

    event PairAdded(address tokenA, address tokenB, address router, address pairAddress);
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"PairAdded","inputs":[{"type":"address","name":"tokenA","internalType":"address","indexed":false},{"type":"address","name":"tokenB","internalType":"address","indexed":false},{"type":"address","name":"router","internalType":"address","indexed":false},{"type":"address","name":"pairAddress","internalType":"address","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addPair","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"address","name":"router","internalType":"address"},{"type":"address","name":"pairAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"burnAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"burnPercent","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"distributeThreshold","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"gasCompPercent","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"bestAmountsOut","internalType":"uint256[]"}],"name":"getBestAmountsOut","inputs":[{"type":"uint256[]","name":"amountsIn","internalType":"uint256[]"},{"type":"address[][]","name":"paths","internalType":"address[][]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getLpAddedForPair","inputs":[{"type":"address","name":"pairAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct HeroABLE.Pair[]","components":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"address","name":"router","internalType":"address"},{"type":"address","name":"pairAddress","internalType":"address"},{"type":"uint256","name":"heroForLp","internalType":"uint256"},{"type":"uint256","name":"totalHeroLpAdded","internalType":"uint256"}]}],"name":"getPairs","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"reserve0s","internalType":"uint256[]"},{"type":"uint256[]","name":"reserve1s","internalType":"uint256[]"}],"name":"getReservesForPairs","inputs":[{"type":"address[]","name":"pairAddresses","internalType":"address[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getTargetLpPairs","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"heroGained","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"heroToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lpAddThreshold","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lpPercent","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minGain","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"multiSwap","inputs":[{"type":"address[][]","name":"swapPaths","internalType":"address[][]"},{"type":"uint256","name":"amountIn","internalType":"uint256"},{"type":"uint256[]","name":"minAmountsOut","internalType":"uint256[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IUniswapV2Router02"}],"name":"nineinchRouter","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"address","name":"router","internalType":"address"},{"type":"address","name":"pairAddress","internalType":"address"},{"type":"uint256","name":"heroForLp","internalType":"uint256"},{"type":"uint256","name":"totalHeroLpAdded","internalType":"uint256"}],"name":"pairs","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pendingGainsDistribution","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IUniswapV2Router02"}],"name":"pulseRouterV1","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IUniswapV2Router02"}],"name":"pulseRouterV2","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"rewardsAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rewardsPercent","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setDistributionSettings","inputs":[{"type":"uint256","name":"_rewardsPercent","internalType":"uint256"},{"type":"uint256","name":"_burnPercent","internalType":"uint256"},{"type":"uint256","name":"_lpPercent","internalType":"uint256"},{"type":"uint256","name":"_gasCompPercent","internalType":"uint256"},{"type":"uint256","name":"_distributeThreshold","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setLpAddThreshold","inputs":[{"type":"uint256","name":"_newThreshold","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinGain","inputs":[{"type":"uint256","name":"_newMinGain","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRewardsAddress","inputs":[{"type":"address","name":"_rewardsAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setSigner","inputs":[{"type":"address","name":"_signer","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setTargetLpPairs","inputs":[{"type":"address[]","name":"lpPairs","internalType":"address[]"},{"type":"bool","name":"enabled","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"targetLpPairs","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"targetedLpMode","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalHeroBurn","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalHeroGasComp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalHeroLp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalHeroReward","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawETH","inputs":[{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawToken","inputs":[{"type":"address","name":"tokenAddress","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IERC20"}],"name":"wpls","inputs":[]},{"type":"receive","stateMutability":"payable"}]
              

Contract Creation Code

Verify & Publish
0x6080604052600480546001600160a01b03199081169091556005805482167335a51dfc82032682e4bda8aaca87b9bc386c3d2717905560068054821673a1077a294dde1b09bb078844df40758a5d0f9a2717905569021e19e0c9bab24000006007819055600855681043561a8829300000600955600a805460ff191690555f600c556019600d8190556032600e55600f556016805482167398bf93ebf5c380c0e6ae8e192a7e2ae08edacc0217905560178054821673165c3410fc91ef562c50559f7d2289febed552d91790556018805490911673eb45a3c4aedd0f47f345fb4c8a1802bb5740d7251790553480156100f6575f5ffd5b5061010033610288565b60108054336001600160a01b031991821617909155600554600380546001600160a01b0392831693168317905560165460405163095ea7b360e01b8152911660048201525f19602482015263095ea7b3906044016020604051808303815f875af1158015610170573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019491906102d7565b5060055460175460405163095ea7b360e01b81526001600160a01b0391821660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af11580156101e7573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061020b91906102d7565b5060055460185460405163095ea7b360e01b81526001600160a01b0391821660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af115801561025e573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061028291906102d7565b506102fd565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f602082840312156102e7575f5ffd5b815180151581146102f6575f5ffd5b9392505050565b6135218061030a5f395ff3fe608060405260043610610241575f3560e01c8063715018a611610134578063a901098a116100b3578063dd239a0311610078578063dd239a03146106af578063de199d6b146106c4578063e091a297146106e3578063f14210a6146106f8578063f2fde38b14610717578063f618fa4514610736575f5ffd5b8063a901098a146105cf578063b91ac788146105e4578063bbca571514610645578063c0973eed14610664578063c5bc6c4714610683575f5ffd5b80638da5cb5b116100f95780638da5cb5b146105375780638f710ca314610553578063927ef7fa146105725780639e281a9814610591578063a21951b6146105b0575f5ffd5b8063715018a6146104a5578063767eb5ef146104b95780637ffab253146104da5780638906758d146104f95780638d5396e914610518575f5ffd5b80634f15999a116101c05780636b7de9da116101855780636b7de9da146104145780636c19e783146104295780636d2b4940146104485780636f23d6941461046757806370d5ae0514610486575f5ffd5b80634f15999a1461035d5780634f24040414610394578063528668ae146103b357806358b09026146103e05780635c7cf032146103f5575f5ffd5b8063259b3ef211610206578063259b3ef2146102dc57806338ce881c146102f15780633f95b43514610312578063448114be146103275780634858692d1461033c575f5ffd5b806303807ee51461024c5780630636241b146102745780630d18480e146102895780631f5815161461029e57806320572c34146102c7575f5ffd5b3661024857005b5f5ffd5b348015610257575f5ffd5b50610261600d5481565b6040519081526020015b60405180910390f35b34801561027f575f5ffd5b50610261600c5481565b348015610294575f5ffd5b5061026160075481565b3480156102a9575f5ffd5b50600a546102b79060ff1681565b604051901515815260200161026b565b3480156102d2575f5ffd5b5061026160085481565b3480156102e7575f5ffd5b5061026160145481565b3480156102fc575f5ffd5b5061030561074b565b60405161026b9190612ce8565b34801561031d575f5ffd5b5061026160135481565b348015610332575f5ffd5b5061026160125481565b348015610347575f5ffd5b5061035b610356366004612d01565b6107ab565b005b348015610368575f5ffd5b5060175461037c906001600160a01b031681565b6040516001600160a01b03909116815260200161026b565b34801561039f575f5ffd5b5061037c6103ae366004612d01565b6107b8565b3480156103be575f5ffd5b506103d26103cd366004612e0a565b6107e0565b60405161026b929190612e73565b3480156103eb575f5ffd5b5061026160115481565b348015610400575f5ffd5b5061035b61040f366004612ea0565b6109d5565b34801561041f575f5ffd5b5061026160095481565b348015610434575f5ffd5b5061035b610443366004612ef1565b610fde565b348015610453575f5ffd5b5060185461037c906001600160a01b031681565b348015610472575f5ffd5b5061035b610481366004612d01565b611008565b348015610491575f5ffd5b5060045461037c906001600160a01b031681565b3480156104b0575f5ffd5b5061035b611015565b3480156104c4575f5ffd5b506104cd611028565b60405161026b9190612f0a565b3480156104e5575f5ffd5b5061035b6104f4366004612fa5565b61115c565b348015610504575f5ffd5b5061035b610513366004612ef1565b611262565b348015610523575f5ffd5b5060165461037c906001600160a01b031681565b348015610542575f5ffd5b505f546001600160a01b031661037c565b34801561055e575f5ffd5b5061035b61056d366004613025565b61128c565b34801561057d575f5ffd5b5060065461037c906001600160a01b031681565b34801561059c575f5ffd5b5061035b6105ab36600461305c565b611380565b3480156105bb575f5ffd5b506102616105ca366004612ef1565b611406565b3480156105da575f5ffd5b50610261600f5481565b3480156105ef575f5ffd5b506106036105fe366004612d01565b6114e4565b604080516001600160a01b03978816815295871660208701529386169385019390935293166060830152608082019290925260a081019190915260c00161026b565b348015610650575f5ffd5b5060055461037c906001600160a01b031681565b34801561066f575f5ffd5b5060035461037c906001600160a01b031681565b34801561068e575f5ffd5b506106a261069d36600461315d565b611538565b60405161026b91906131c0565b3480156106ba575f5ffd5b5061026160155481565b3480156106cf575f5ffd5b5061035b6106de3660046131d2565b6117e7565b3480156106ee575f5ffd5b50610261600e5481565b348015610703575f5ffd5b5061035b610712366004612d01565b611f89565b348015610722575f5ffd5b5061035b610731366004612ef1565b611fcb565b348015610741575f5ffd5b5061026160025481565b6060600b8054806020026020016040519081016040528092919081815260200182805480156107a157602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610783575b5050505050905090565b6107b3612044565b600755565b600b81815481106107c7575f80fd5b5f918252602090912001546001600160a01b0316905081565b80516060908190806001600160401b038111156107ff576107ff612d18565b604051908082528060200260200182016040528015610828578160200160208202803683370190505b509250806001600160401b0381111561084357610843612d18565b60405190808252806020026020018201604052801561086c578160200160208202803683370190505b5091505f5b818110156109ce575f85828151811061088c5761088c61323d565b602002602001015190505f6001600160a01b0316816001600160a01b0316036108d05760405162461bcd60e51b81526004016108c790613251565b60405180910390fd5b806001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa92505050801561092a575060408051601f3d908101601f1916820190925261092791810190613295565b60015b610971575f8583815181106109415761094161323d565b6020026020010181815250505f8483815181106109605761096061323d565b6020026020010181815250506109c5565b826001600160701b031688868151811061098d5761098d61323d565b602002602001018181525050816001600160701b03168786815181106109b5576109b561323d565b6020026020010181815250505050505b50600101610871565b5050915091565b6109dd612044565b6001600160a01b038416158015906109fd57506001600160a01b03831615155b610a495760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420746f6b656e2061646472657373657300000000000000000060448201526064016108c7565b6001600160a01b038216610a985760405162461bcd60e51b8152602060048201526016602482015275496e76616c696420726f75746572206164647265737360501b60448201526064016108c7565b6001600160a01b038116610abe5760405162461bcd60e51b81526004016108c790613251565b6016546001600160a01b0383811691161480610ae757506017546001600160a01b038381169116145b80610aff57506018546001600160a01b038381169116145b610b425760405162461bcd60e51b8152602060048201526014602482015273149bdd5d195c881b9bdd081cdd5c1c1bdc9d195960621b60448201526064016108c7565b60165460405163095ea7b360e01b81526001600160a01b038681169263095ea7b392610b7792909116905f19906004016132d6565b6020604051808303815f875af1158015610b93573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bb791906132ef565b5060165460405163095ea7b360e01b81526001600160a01b038581169263095ea7b392610bed92909116905f19906004016132d6565b6020604051808303815f875af1158015610c09573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c2d91906132ef565b5060175460405163095ea7b360e01b81526001600160a01b038681169263095ea7b392610c6392909116905f19906004016132d6565b6020604051808303815f875af1158015610c7f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ca391906132ef565b5060175460405163095ea7b360e01b81526001600160a01b038581169263095ea7b392610cd992909116905f19906004016132d6565b6020604051808303815f875af1158015610cf5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d1991906132ef565b5060185460405163095ea7b360e01b81526001600160a01b038681169263095ea7b392610d4f92909116905f19906004016132d6565b6020604051808303815f875af1158015610d6b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d8f91906132ef565b5060185460405163095ea7b360e01b81526001600160a01b038581169263095ea7b392610dc592909116905f19906004016132d6565b6020604051808303815f875af1158015610de1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e0591906132ef565b506040805160c0810182526001600160a01b03808716825285811660208301908152858216838501908152858316606085019081525f6080860181815260a087018281526001805480820182559352965160069092027fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6810180549388166001600160a01b031994851617905594517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf78601805491881691841691909117905592517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf88501805491871691831691909117905590517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf9840180549190951691161790925590517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfa82015590517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfb90910155517f055f867b470418392a4b315ae5a808843e9c5ffb49ad6ba0b27413205d68904490610fd09086908690869086906001600160a01b03948516815292841660208401529083166040830152909116606082015260800190565b60405180910390a150505050565b610fe6612044565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b611010612044565b600955565b61101d612044565b6110265f61209d565b565b6001546060905f816001600160401b0381111561104757611047612d18565b6040519080825280602002602001820160405280156110a557816020015b6040805160c0810182525f8082526020808301829052928201819052606082018190526080820181905260a082015282525f199092019101816110655790505b5090505f5b8281101561115557600181815481106110c5576110c561323d565b5f9182526020918290206040805160c081018252600690930290910180546001600160a01b03908116845260018201548116948401949094526002810154841691830191909152600381015490921660608201526004820154608082015260059091015460a082015282518390839081106111425761114261323d565b60209081029190910101526001016110aa565b5092915050565b611164612044565b60048211156111855760405162461bcd60e51b81526004016108c79061330a565b5f5b82811015611215575f8484838181106111a2576111a261323d565b90506020020160208101906111b79190612ef1565b6001600160a01b03160361120d5760405162461bcd60e51b815260206004820152601960248201527f496e76616c6964204c502074617267657420616464726573730000000000000060448201526064016108c7565b600101611187565b50611222600b8484612c30565b50600a805460ff191682151590811790915560ff16151560010361125d578161125d5760405162461bcd60e51b81526004016108c79061330a565b505050565b61126a612044565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b611294612044565b600c859055600d849055600e839055600f829055600881905581836112b98688613364565b6112c39190613364565b6112cd9190613364565b6064146113125760405162461bcd60e51b8152602060048201526013602482015272496e76616c69642070657263656e746167657360681b60448201526064016108c7565b6032600f5411156113795760405162461bcd60e51b815260206004820152602b60248201527f4d61782035302070657263656e7420616c6c6f77656420746f2067617320636f60448201526a36b832b739b0ba34b7b71760a91b60648201526084016108c7565b5050505050565b611388612044565b816001600160a01b031663a9059cbb6113a85f546001600160a01b031690565b836040518363ffffffff1660e01b81526004016113c69291906132d6565b6020604051808303815f875af11580156113e2573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061125d91906132ef565b5f6001600160a01b03821661142d5760405162461bcd60e51b81526004016108c790613251565b5f5b6001548110156114aa57826001600160a01b0316600182815481106114565761145661323d565b5f9182526020909120600360069092020101546001600160a01b0316036114a2576001818154811061148a5761148a61323d565b905f5260205f20906006020160050154915050919050565b60010161142f565b5060405162461bcd60e51b815260206004820152600e60248201526d14185a5c881b9bdd08199bdd5b9960921b60448201526064016108c7565b600181815481106114f3575f80fd5b5f9182526020909120600690910201805460018201546002830154600384015460048501546005909501546001600160a01b0394851696509284169491841693169186565b606081518351146115955760405162461bcd60e51b815260206004820152602160248201527f416d6f756e747320616e64207061746873206c656e677468206d69736d6174636044820152600d60fb1b60648201526084016108c7565b8251806001600160401b038111156115af576115af612d18565b6040519080825280602002602001820160405280156115d8578160200160208202803683370190505b50604080516003808252608082019092529193505f919060208201606080368337505060165482519293506001600160a01b0316918391505f9061161e5761161e61323d565b6001600160a01b03928316602091820292909201015260175482519116908290600190811061164f5761164f61323d565b6001600160a01b0392831660209182029290920101526018548251911690829060029081106116805761168061323d565b6001600160a01b03909216602092830291909101909101525f5b828110156117de575f8682815181106116b5576116b561323d565b602002602001015190505f8683815181106116d2576116d261323d565b602090810291909101015190505f805b85518110156117b4578581815181106116fd576116fd61323d565b60200260200101516001600160a01b031663d06ca61f85856040518363ffffffff1660e01b815260040161173292919061337d565b5f60405180830381865afa92505050801561176e57506040513d5f823e601f3d908101601f1916820160405261176b9190810190613395565b60015b156117ac575f81600183516117839190613425565b815181106117935761179361323d565b60200260200101519050838111156117a9578093505b50505b6001016116e2565b50808785815181106117c8576117c861323d565b602090810291909101015250505060010161169a565b50505092915050565b6010546001600160a01b0316331461182e5760405162461bcd60e51b815260206004820152600a6024820152692737ba1039b4b3b732b960b11b60448201526064016108c7565b805183511461187f5760405162461bcd60e51b815260206004820181905260248201527f506174687320616e64206d696e416d6f756e74734f7574206d69736d6174636860448201526064016108c7565b60018351116118d05760405162461bcd60e51b815260206004820152601b60248201527f4174206c656173742074776f207377617073207265717569726564000000000060448201526064016108c7565b825182905f906001600160401b038111156118ed576118ed612d18565b604051908082528060200260200182016040528015611916578160200160208202803683370190505b5090505f85516001600160401b0381111561193357611933612d18565b60405190808252806020026020018201604052801561195c578160200160208202803683370190505b50604080516003808252608082019092529192505f919060208201606080368337505060165482519293506001600160a01b0316918391505f906119a2576119a261323d565b6001600160a01b0392831660209182029290920101526017548251911690829060019081106119d3576119d361323d565b6001600160a01b039283166020918202929092010152601854825191169082906002908110611a0457611a0461323d565b6001600160a01b03909216602092830291909101909101525f5b8751811015611c6457878181518110611a3957611a3961323d565b602002602001015151600214611aa35760405162461bcd60e51b815260206004820152602960248201527f4561636820737761702070617468206d75737420686176652065786163746c79604482015268203220746f6b656e7360b81b60648201526084016108c7565b5f80805b8451811015611bae57848181518110611ac257611ac261323d565b60200260200101516001600160a01b031663d06ca61f898d8781518110611aeb57611aeb61323d565b60200260200101516040518363ffffffff1660e01b8152600401611b1092919061337d565b5f60405180830381865afa925050508015611b4c57506040513d5f823e601f3d908101601f19168201604052611b499190810190613395565b60015b15611ba6575f8160018351611b619190613425565b81518110611b7157611b7161323d565b6020026020010151905084811115611ba357809450868381518110611b9857611b9861323d565b602002602001015193505b50505b600101611aa7565b506001600160a01b038116611c0f5760405162461bcd60e51b815260206004820152602160248201527f4e6f207375697461626c6520726f7574657220666f756e6420666f72207061746044820152600d60fb1b60648201526084016108c7565b81868481518110611c2257611c2261323d565b60200260200101818152505080858481518110611c4157611c4161323d565b6001600160a01b0390921660209283029190910190910152509450600101611a1e565b50600954611c729087613364565b8360018951611c819190613425565b81518110611c9157611c9161323d565b60200260200101511015611ce75760405162461bcd60e51b815260206004820152601760248201527f4d757374206761696e206865726f206f766572616c6c2e00000000000000000060448201526064016108c7565b8593505f5b8751811015611f43575f888281518110611d0857611d0861323d565b602002602001015160018a8481518110611d2457611d2461323d565b602002602001015151611d379190613425565b81518110611d4757611d4761323d565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611d95573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611db99190613438565b9050838281518110611dcd57611dcd61323d565b60200260200101516001600160a01b0316635c11d79587898581518110611df657611df661323d565b60200260200101518c8681518110611e1057611e1061323d565b602002602001015130426040518663ffffffff1660e01b8152600401611e3a95949392919061344f565b5f604051808303815f87803b158015611e51575f5ffd5b505af1158015611e63573d5f5f3e3d5ffd5b505050505f898381518110611e7a57611e7a61323d565b602002602001015160018b8581518110611e9657611e9661323d565b602002602001015151611ea99190613425565b81518110611eb957611eb961323d565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611f07573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f2b9190613438565b9050611f378282613425565b96505050600101611cec565b505f868511611f52575f611f5c565b611f5c8786613425565b90508060025f828254611f6f9190613364565b90915550611f7f905081896120ec565b5050505050505050565b611f91612044565b5f80546040516001600160a01b039091169183156108fc02918491818181858888f19350505050158015611fc7573d5f5f3e3d5ffd5b5050565b611fd3612044565b6001600160a01b0381166120385760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108c7565b6120418161209d565b50565b5f546001600160a01b031633146110265760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108c7565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600e545f90156124ed576064600e5484612106919061348a565b61211091906134a1565b90508060135f8282546121239190613364565b9091555050600a5460ff16801561213b5750600b5415155b156122d157600b545f9061214f90836134a1565b90505f5b600b548110156122ca575f805b60015481101561226357600b838154811061217d5761217d61323d565b5f91825260209091200154600180546001600160a01b0390921691839081106121a8576121a861323d565b5f9182526020909120600360069092020101546001600160a01b03160361225b5783600182815481106121dd576121dd61323d565b905f5260205f2090600602016004015f8282546121fa9190613364565b909155505060075460018054839081106122165761221661323d565b905f5260205f209060060201600401541061225257612252600182815481106122415761224161323d565b905f5260205f20906006020161251f565b60019150612263565b600101612160565b50806122c15760405162461bcd60e51b815260206004820152602760248201527f546172676574204c502070616972206e6f7420666f756e6420696e20706169726044820152667320617272617960c81b60648201526084016108c7565b50600101612153565b50506124ed565b5f82600184516122e19190613425565b815181106122f1576122f161323d565b60200260200101515f8151811061230a5761230a61323d565b602002602001015190505f83600185516123249190613425565b815181106123345761233461323d565b602002602001015160018151811061234e5761234e61323d565b602002602001015190505f5f90505b6001548110156124e957826001600160a01b0316600182815481106123845761238461323d565b5f9182526020909120600690910201546001600160a01b03161480156123e05750816001600160a01b0316600182815481106123c2576123c261323d565b5f9182526020909120600160069092020101546001600160a01b0316145b8061245f5750816001600160a01b0316600182815481106124035761240361323d565b5f9182526020909120600690910201546001600160a01b031614801561245f5750826001600160a01b0316600182815481106124415761244161323d565b5f9182526020909120600160069092020101546001600160a01b0316145b156124e15783600182815481106124785761247861323d565b905f5260205f2090600602016004015f8282546124959190613364565b909155505060075460018054839081106124b1576124b161323d565b905f5260205f20906006020160040154106124dc576124dc600182815481106122415761224161323d565b6124e9565b60010161235d565b5050505b6124f78184613425565b60155f8282546125079190613364565b90915550506008546015541061125d5761125d612975565b6004810180545f918290556005830180549192839261253f908490613364565b90915550506002820154825460018401546005546001600160a01b039384169392831692918216915f9116831461257757818361257a565b82825b6005546040516370a0823160e01b81523060048201529193505f92506001600160a01b0316906370a0823190602401602060405180830381865afa1580156125c4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125e89190613438565b90505f861180156125f95750858110155b1561296c575f61260a6002886134a1565b6040805160028082526060820183529293505f929091602083019080368337505060055482519293506001600160a01b0316918391505f9061264e5761264e61323d565b60200260200101906001600160a01b031690816001600160a01b03168152505083816001815181106126825761268261323d565b6001600160a01b0392831660209182029290920101526040516370a0823160e01b81523060048201525f918616906370a0823190602401602060405180830381865afa1580156126d4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126f89190613438565b604051635c11d79560e01b81529091506001600160a01b03891690635c11d7959061272f9086905f9087903090429060040161344f565b5f604051808303815f87803b158015612746575f5ffd5b505af1158015612758573d5f5f3e3d5ffd5b50506040516370a0823160e01b81523060048201525f92508391506001600160a01b038816906370a0823190602401602060405180830381865afa1580156127a2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127c69190613438565b6127d09190613425565b6005549091505f9081906001600160a01b03808d169163e8e3370091168a898786806128035f546001600160a01b031690565b60405160e089901b6001600160e01b03191681526001600160a01b039788166004820152958716602487015260448601949094526064850192909252608484015260a483015290911660c48201524260e4820152610104016060604051808303815f875af1158015612877573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061289b91906134c0565b5091509150818611156128cf575f6128b38388613425565b9050808e6004015f8282546128c89190613364565b9091555050505b80831115612965575f6128e28285613425565b9050886001600160a01b031663a9059cbb6129045f546001600160a01b031690565b836040518363ffffffff1660e01b81526004016129229291906132d6565b6020604051808303815f875af115801561293e573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061296291906132ef565b50505b5050505050505b50505050505050565b5f600e5460646129859190613425565b600c54601554612995919061348a565b61299f91906134a1565b90505f600e5460646129b19190613425565b600d546015546129c1919061348a565b6129cb91906134a1565b90505f600e5460646129dd9190613425565b600f546015546129ed919061348a565b6129f791906134a1565b90508215612a8d5760055460035460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb92612a359291169087906004016132d6565b6020604051808303815f875af1158015612a51573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a7591906132ef565b508260125f828254612a879190613364565b90915550505b8115612b21576005546004805460405163a9059cbb60e01b81526001600160a01b039384169363a9059cbb93612ac993909116918791016132d6565b6020604051808303815f875af1158015612ae5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b0991906132ef565b508160115f828254612b1b9190613364565b90915550505b8015612c27576040805160028082526060820183525f92602083019080368337505060055482519293506001600160a01b0316918391505f90612b6657612b6661323d565b6001600160a01b039283166020918202929092010152600654825191169082906001908110612b9757612b9761323d565b6001600160a01b03928316602091820292909201015260175460105460405163791ac94760e01b81529183169263791ac94792612be29287925f92889290911690429060040161344f565b5f604051808303815f87803b158015612bf9575f5ffd5b505af1158015612c0b573d5f5f3e3d5ffd5b505050508160145f828254612c209190613364565b9091555050505b50505f60155550565b828054828255905f5260205f20908101928215612c81579160200282015b82811115612c815781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190612c4e565b50612c8d929150612c91565b5090565b5b80821115612c8d575f8155600101612c92565b5f8151808452602084019350602083015f5b82811015612cde5781516001600160a01b0316865260209586019590910190600101612cb7565b5093949350505050565b602081525f612cfa6020830184612ca5565b9392505050565b5f60208284031215612d11575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715612d5457612d54612d18565b604052919050565b5f6001600160401b03821115612d7457612d74612d18565b5060051b60200190565b80356001600160a01b0381168114612d94575f5ffd5b919050565b5f82601f830112612da8575f5ffd5b8135612dbb612db682612d5c565b612d2c565b8082825260208201915060208360051b860101925085831115612ddc575f5ffd5b602085015b83811015612e0057612df281612d7e565b835260209283019201612de1565b5095945050505050565b5f60208284031215612e1a575f5ffd5b81356001600160401b03811115612e2f575f5ffd5b612e3b84828501612d99565b949350505050565b5f8151808452602084019350602083015f5b82811015612cde578151865260209586019590910190600101612e55565b604081525f612e856040830185612e43565b8281036020840152612e978185612e43565b95945050505050565b5f5f5f5f60808587031215612eb3575f5ffd5b612ebc85612d7e565b9350612eca60208601612d7e565b9250612ed860408601612d7e565b9150612ee660608601612d7e565b905092959194509250565b5f60208284031215612f01575f5ffd5b612cfa82612d7e565b602080825282518282018190525f918401906040840190835b81811015612f8d57835180516001600160a01b039081168552602080830151821681870152604080840151831690870152606080840151909216918601919091526080808301519086015260a091820151918501919091529093019260c090920191600101612f23565b509095945050505050565b8015158114612041575f5ffd5b5f5f5f60408486031215612fb7575f5ffd5b83356001600160401b03811115612fcc575f5ffd5b8401601f81018613612fdc575f5ffd5b80356001600160401b03811115612ff1575f5ffd5b8660208260051b8401011115613005575f5ffd5b60209182019450925084013561301a81612f98565b809150509250925092565b5f5f5f5f5f60a08688031215613039575f5ffd5b505083359560208501359550604085013594606081013594506080013592509050565b5f5f6040838503121561306d575f5ffd5b61307683612d7e565b946020939093013593505050565b5f82601f830112613093575f5ffd5b81356130a1612db682612d5c565b8082825260208201915060208360051b8601019250858311156130c2575f5ffd5b602085015b83811015612e005780358352602092830192016130c7565b5f82601f8301126130ee575f5ffd5b81356130fc612db682612d5c565b8082825260208201915060208360051b86010192508583111561311d575f5ffd5b602085015b83811015612e005780356001600160401b0381111561313f575f5ffd5b61314e886020838a0101612d99565b84525060209283019201613122565b5f5f6040838503121561316e575f5ffd5b82356001600160401b03811115613183575f5ffd5b61318f85828601613084565b92505060208301356001600160401b038111156131aa575f5ffd5b6131b6858286016130df565b9150509250929050565b602081525f612cfa6020830184612e43565b5f5f5f606084860312156131e4575f5ffd5b83356001600160401b038111156131f9575f5ffd5b613205868287016130df565b9350506020840135915060408401356001600160401b03811115613227575f5ffd5b61323386828701613084565b9150509250925092565b634e487b7160e01b5f52603260045260245ffd5b602080825260149082015273496e76616c69642070616972206164647265737360601b604082015260600190565b80516001600160701b0381168114612d94575f5ffd5b5f5f5f606084860312156132a7575f5ffd5b6132b08461327f565b92506132be6020850161327f565b9150604084015163ffffffff8116811461301a575f5ffd5b6001600160a01b03929092168252602082015260400190565b5f602082840312156132ff575f5ffd5b8151612cfa81612f98565b60208082526026908201527f43616e6e6f7420736574206d6f7265207468616e2034204c502074617267657460408201526520706169727360d01b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561337757613377613350565b92915050565b828152604060208201525f612e3b6040830184612ca5565b5f602082840312156133a5575f5ffd5b81516001600160401b038111156133ba575f5ffd5b8201601f810184136133ca575f5ffd5b80516133d8612db682612d5c565b8082825260208201915060208360051b8501019250868311156133f9575f5ffd5b6020840193505b8284101561341b578351825260209384019390910190613400565b9695505050505050565b8181038181111561337757613377613350565b5f60208284031215613448575f5ffd5b5051919050565b85815284602082015260a060408201525f61346d60a0830186612ca5565b6001600160a01b0394909416606083015250608001529392505050565b808202811582820484141761337757613377613350565b5f826134bb57634e487b7160e01b5f52601260045260245ffd5b500490565b5f5f5f606084860312156134d2575f5ffd5b505081516020830151604090930151909492935091905056fea264697066735822122005febe6a461ba76c0b80b47428d855c536521aaaa0253f7647fa59a6707e707d64736f6c634300081b0033

Deployed ByteCode

0x608060405260043610610241575f3560e01c8063715018a611610134578063a901098a116100b3578063dd239a0311610078578063dd239a03146106af578063de199d6b146106c4578063e091a297146106e3578063f14210a6146106f8578063f2fde38b14610717578063f618fa4514610736575f5ffd5b8063a901098a146105cf578063b91ac788146105e4578063bbca571514610645578063c0973eed14610664578063c5bc6c4714610683575f5ffd5b80638da5cb5b116100f95780638da5cb5b146105375780638f710ca314610553578063927ef7fa146105725780639e281a9814610591578063a21951b6146105b0575f5ffd5b8063715018a6146104a5578063767eb5ef146104b95780637ffab253146104da5780638906758d146104f95780638d5396e914610518575f5ffd5b80634f15999a116101c05780636b7de9da116101855780636b7de9da146104145780636c19e783146104295780636d2b4940146104485780636f23d6941461046757806370d5ae0514610486575f5ffd5b80634f15999a1461035d5780634f24040414610394578063528668ae146103b357806358b09026146103e05780635c7cf032146103f5575f5ffd5b8063259b3ef211610206578063259b3ef2146102dc57806338ce881c146102f15780633f95b43514610312578063448114be146103275780634858692d1461033c575f5ffd5b806303807ee51461024c5780630636241b146102745780630d18480e146102895780631f5815161461029e57806320572c34146102c7575f5ffd5b3661024857005b5f5ffd5b348015610257575f5ffd5b50610261600d5481565b6040519081526020015b60405180910390f35b34801561027f575f5ffd5b50610261600c5481565b348015610294575f5ffd5b5061026160075481565b3480156102a9575f5ffd5b50600a546102b79060ff1681565b604051901515815260200161026b565b3480156102d2575f5ffd5b5061026160085481565b3480156102e7575f5ffd5b5061026160145481565b3480156102fc575f5ffd5b5061030561074b565b60405161026b9190612ce8565b34801561031d575f5ffd5b5061026160135481565b348015610332575f5ffd5b5061026160125481565b348015610347575f5ffd5b5061035b610356366004612d01565b6107ab565b005b348015610368575f5ffd5b5060175461037c906001600160a01b031681565b6040516001600160a01b03909116815260200161026b565b34801561039f575f5ffd5b5061037c6103ae366004612d01565b6107b8565b3480156103be575f5ffd5b506103d26103cd366004612e0a565b6107e0565b60405161026b929190612e73565b3480156103eb575f5ffd5b5061026160115481565b348015610400575f5ffd5b5061035b61040f366004612ea0565b6109d5565b34801561041f575f5ffd5b5061026160095481565b348015610434575f5ffd5b5061035b610443366004612ef1565b610fde565b348015610453575f5ffd5b5060185461037c906001600160a01b031681565b348015610472575f5ffd5b5061035b610481366004612d01565b611008565b348015610491575f5ffd5b5060045461037c906001600160a01b031681565b3480156104b0575f5ffd5b5061035b611015565b3480156104c4575f5ffd5b506104cd611028565b60405161026b9190612f0a565b3480156104e5575f5ffd5b5061035b6104f4366004612fa5565b61115c565b348015610504575f5ffd5b5061035b610513366004612ef1565b611262565b348015610523575f5ffd5b5060165461037c906001600160a01b031681565b348015610542575f5ffd5b505f546001600160a01b031661037c565b34801561055e575f5ffd5b5061035b61056d366004613025565b61128c565b34801561057d575f5ffd5b5060065461037c906001600160a01b031681565b34801561059c575f5ffd5b5061035b6105ab36600461305c565b611380565b3480156105bb575f5ffd5b506102616105ca366004612ef1565b611406565b3480156105da575f5ffd5b50610261600f5481565b3480156105ef575f5ffd5b506106036105fe366004612d01565b6114e4565b604080516001600160a01b03978816815295871660208701529386169385019390935293166060830152608082019290925260a081019190915260c00161026b565b348015610650575f5ffd5b5060055461037c906001600160a01b031681565b34801561066f575f5ffd5b5060035461037c906001600160a01b031681565b34801561068e575f5ffd5b506106a261069d36600461315d565b611538565b60405161026b91906131c0565b3480156106ba575f5ffd5b5061026160155481565b3480156106cf575f5ffd5b5061035b6106de3660046131d2565b6117e7565b3480156106ee575f5ffd5b50610261600e5481565b348015610703575f5ffd5b5061035b610712366004612d01565b611f89565b348015610722575f5ffd5b5061035b610731366004612ef1565b611fcb565b348015610741575f5ffd5b5061026160025481565b6060600b8054806020026020016040519081016040528092919081815260200182805480156107a157602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610783575b5050505050905090565b6107b3612044565b600755565b600b81815481106107c7575f80fd5b5f918252602090912001546001600160a01b0316905081565b80516060908190806001600160401b038111156107ff576107ff612d18565b604051908082528060200260200182016040528015610828578160200160208202803683370190505b509250806001600160401b0381111561084357610843612d18565b60405190808252806020026020018201604052801561086c578160200160208202803683370190505b5091505f5b818110156109ce575f85828151811061088c5761088c61323d565b602002602001015190505f6001600160a01b0316816001600160a01b0316036108d05760405162461bcd60e51b81526004016108c790613251565b60405180910390fd5b806001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa92505050801561092a575060408051601f3d908101601f1916820190925261092791810190613295565b60015b610971575f8583815181106109415761094161323d565b6020026020010181815250505f8483815181106109605761096061323d565b6020026020010181815250506109c5565b826001600160701b031688868151811061098d5761098d61323d565b602002602001018181525050816001600160701b03168786815181106109b5576109b561323d565b6020026020010181815250505050505b50600101610871565b5050915091565b6109dd612044565b6001600160a01b038416158015906109fd57506001600160a01b03831615155b610a495760405162461bcd60e51b815260206004820152601760248201527f496e76616c696420746f6b656e2061646472657373657300000000000000000060448201526064016108c7565b6001600160a01b038216610a985760405162461bcd60e51b8152602060048201526016602482015275496e76616c696420726f75746572206164647265737360501b60448201526064016108c7565b6001600160a01b038116610abe5760405162461bcd60e51b81526004016108c790613251565b6016546001600160a01b0383811691161480610ae757506017546001600160a01b038381169116145b80610aff57506018546001600160a01b038381169116145b610b425760405162461bcd60e51b8152602060048201526014602482015273149bdd5d195c881b9bdd081cdd5c1c1bdc9d195960621b60448201526064016108c7565b60165460405163095ea7b360e01b81526001600160a01b038681169263095ea7b392610b7792909116905f19906004016132d6565b6020604051808303815f875af1158015610b93573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bb791906132ef565b5060165460405163095ea7b360e01b81526001600160a01b038581169263095ea7b392610bed92909116905f19906004016132d6565b6020604051808303815f875af1158015610c09573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c2d91906132ef565b5060175460405163095ea7b360e01b81526001600160a01b038681169263095ea7b392610c6392909116905f19906004016132d6565b6020604051808303815f875af1158015610c7f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ca391906132ef565b5060175460405163095ea7b360e01b81526001600160a01b038581169263095ea7b392610cd992909116905f19906004016132d6565b6020604051808303815f875af1158015610cf5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d1991906132ef565b5060185460405163095ea7b360e01b81526001600160a01b038681169263095ea7b392610d4f92909116905f19906004016132d6565b6020604051808303815f875af1158015610d6b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d8f91906132ef565b5060185460405163095ea7b360e01b81526001600160a01b038581169263095ea7b392610dc592909116905f19906004016132d6565b6020604051808303815f875af1158015610de1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e0591906132ef565b506040805160c0810182526001600160a01b03808716825285811660208301908152858216838501908152858316606085019081525f6080860181815260a087018281526001805480820182559352965160069092027fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6810180549388166001600160a01b031994851617905594517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf78601805491881691841691909117905592517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf88501805491871691831691909117905590517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf9840180549190951691161790925590517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfa82015590517fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cfb90910155517f055f867b470418392a4b315ae5a808843e9c5ffb49ad6ba0b27413205d68904490610fd09086908690869086906001600160a01b03948516815292841660208401529083166040830152909116606082015260800190565b60405180910390a150505050565b610fe6612044565b601080546001600160a01b0319166001600160a01b0392909216919091179055565b611010612044565b600955565b61101d612044565b6110265f61209d565b565b6001546060905f816001600160401b0381111561104757611047612d18565b6040519080825280602002602001820160405280156110a557816020015b6040805160c0810182525f8082526020808301829052928201819052606082018190526080820181905260a082015282525f199092019101816110655790505b5090505f5b8281101561115557600181815481106110c5576110c561323d565b5f9182526020918290206040805160c081018252600690930290910180546001600160a01b03908116845260018201548116948401949094526002810154841691830191909152600381015490921660608201526004820154608082015260059091015460a082015282518390839081106111425761114261323d565b60209081029190910101526001016110aa565b5092915050565b611164612044565b60048211156111855760405162461bcd60e51b81526004016108c79061330a565b5f5b82811015611215575f8484838181106111a2576111a261323d565b90506020020160208101906111b79190612ef1565b6001600160a01b03160361120d5760405162461bcd60e51b815260206004820152601960248201527f496e76616c6964204c502074617267657420616464726573730000000000000060448201526064016108c7565b600101611187565b50611222600b8484612c30565b50600a805460ff191682151590811790915560ff16151560010361125d578161125d5760405162461bcd60e51b81526004016108c79061330a565b505050565b61126a612044565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b611294612044565b600c859055600d849055600e839055600f829055600881905581836112b98688613364565b6112c39190613364565b6112cd9190613364565b6064146113125760405162461bcd60e51b8152602060048201526013602482015272496e76616c69642070657263656e746167657360681b60448201526064016108c7565b6032600f5411156113795760405162461bcd60e51b815260206004820152602b60248201527f4d61782035302070657263656e7420616c6c6f77656420746f2067617320636f60448201526a36b832b739b0ba34b7b71760a91b60648201526084016108c7565b5050505050565b611388612044565b816001600160a01b031663a9059cbb6113a85f546001600160a01b031690565b836040518363ffffffff1660e01b81526004016113c69291906132d6565b6020604051808303815f875af11580156113e2573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061125d91906132ef565b5f6001600160a01b03821661142d5760405162461bcd60e51b81526004016108c790613251565b5f5b6001548110156114aa57826001600160a01b0316600182815481106114565761145661323d565b5f9182526020909120600360069092020101546001600160a01b0316036114a2576001818154811061148a5761148a61323d565b905f5260205f20906006020160050154915050919050565b60010161142f565b5060405162461bcd60e51b815260206004820152600e60248201526d14185a5c881b9bdd08199bdd5b9960921b60448201526064016108c7565b600181815481106114f3575f80fd5b5f9182526020909120600690910201805460018201546002830154600384015460048501546005909501546001600160a01b0394851696509284169491841693169186565b606081518351146115955760405162461bcd60e51b815260206004820152602160248201527f416d6f756e747320616e64207061746873206c656e677468206d69736d6174636044820152600d60fb1b60648201526084016108c7565b8251806001600160401b038111156115af576115af612d18565b6040519080825280602002602001820160405280156115d8578160200160208202803683370190505b50604080516003808252608082019092529193505f919060208201606080368337505060165482519293506001600160a01b0316918391505f9061161e5761161e61323d565b6001600160a01b03928316602091820292909201015260175482519116908290600190811061164f5761164f61323d565b6001600160a01b0392831660209182029290920101526018548251911690829060029081106116805761168061323d565b6001600160a01b03909216602092830291909101909101525f5b828110156117de575f8682815181106116b5576116b561323d565b602002602001015190505f8683815181106116d2576116d261323d565b602090810291909101015190505f805b85518110156117b4578581815181106116fd576116fd61323d565b60200260200101516001600160a01b031663d06ca61f85856040518363ffffffff1660e01b815260040161173292919061337d565b5f60405180830381865afa92505050801561176e57506040513d5f823e601f3d908101601f1916820160405261176b9190810190613395565b60015b156117ac575f81600183516117839190613425565b815181106117935761179361323d565b60200260200101519050838111156117a9578093505b50505b6001016116e2565b50808785815181106117c8576117c861323d565b602090810291909101015250505060010161169a565b50505092915050565b6010546001600160a01b0316331461182e5760405162461bcd60e51b815260206004820152600a6024820152692737ba1039b4b3b732b960b11b60448201526064016108c7565b805183511461187f5760405162461bcd60e51b815260206004820181905260248201527f506174687320616e64206d696e416d6f756e74734f7574206d69736d6174636860448201526064016108c7565b60018351116118d05760405162461bcd60e51b815260206004820152601b60248201527f4174206c656173742074776f207377617073207265717569726564000000000060448201526064016108c7565b825182905f906001600160401b038111156118ed576118ed612d18565b604051908082528060200260200182016040528015611916578160200160208202803683370190505b5090505f85516001600160401b0381111561193357611933612d18565b60405190808252806020026020018201604052801561195c578160200160208202803683370190505b50604080516003808252608082019092529192505f919060208201606080368337505060165482519293506001600160a01b0316918391505f906119a2576119a261323d565b6001600160a01b0392831660209182029290920101526017548251911690829060019081106119d3576119d361323d565b6001600160a01b039283166020918202929092010152601854825191169082906002908110611a0457611a0461323d565b6001600160a01b03909216602092830291909101909101525f5b8751811015611c6457878181518110611a3957611a3961323d565b602002602001015151600214611aa35760405162461bcd60e51b815260206004820152602960248201527f4561636820737761702070617468206d75737420686176652065786163746c79604482015268203220746f6b656e7360b81b60648201526084016108c7565b5f80805b8451811015611bae57848181518110611ac257611ac261323d565b60200260200101516001600160a01b031663d06ca61f898d8781518110611aeb57611aeb61323d565b60200260200101516040518363ffffffff1660e01b8152600401611b1092919061337d565b5f60405180830381865afa925050508015611b4c57506040513d5f823e601f3d908101601f19168201604052611b499190810190613395565b60015b15611ba6575f8160018351611b619190613425565b81518110611b7157611b7161323d565b6020026020010151905084811115611ba357809450868381518110611b9857611b9861323d565b602002602001015193505b50505b600101611aa7565b506001600160a01b038116611c0f5760405162461bcd60e51b815260206004820152602160248201527f4e6f207375697461626c6520726f7574657220666f756e6420666f72207061746044820152600d60fb1b60648201526084016108c7565b81868481518110611c2257611c2261323d565b60200260200101818152505080858481518110611c4157611c4161323d565b6001600160a01b0390921660209283029190910190910152509450600101611a1e565b50600954611c729087613364565b8360018951611c819190613425565b81518110611c9157611c9161323d565b60200260200101511015611ce75760405162461bcd60e51b815260206004820152601760248201527f4d757374206761696e206865726f206f766572616c6c2e00000000000000000060448201526064016108c7565b8593505f5b8751811015611f43575f888281518110611d0857611d0861323d565b602002602001015160018a8481518110611d2457611d2461323d565b602002602001015151611d379190613425565b81518110611d4757611d4761323d565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611d95573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611db99190613438565b9050838281518110611dcd57611dcd61323d565b60200260200101516001600160a01b0316635c11d79587898581518110611df657611df661323d565b60200260200101518c8681518110611e1057611e1061323d565b602002602001015130426040518663ffffffff1660e01b8152600401611e3a95949392919061344f565b5f604051808303815f87803b158015611e51575f5ffd5b505af1158015611e63573d5f5f3e3d5ffd5b505050505f898381518110611e7a57611e7a61323d565b602002602001015160018b8581518110611e9657611e9661323d565b602002602001015151611ea99190613425565b81518110611eb957611eb961323d565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa158015611f07573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f2b9190613438565b9050611f378282613425565b96505050600101611cec565b505f868511611f52575f611f5c565b611f5c8786613425565b90508060025f828254611f6f9190613364565b90915550611f7f905081896120ec565b5050505050505050565b611f91612044565b5f80546040516001600160a01b039091169183156108fc02918491818181858888f19350505050158015611fc7573d5f5f3e3d5ffd5b5050565b611fd3612044565b6001600160a01b0381166120385760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016108c7565b6120418161209d565b50565b5f546001600160a01b031633146110265760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016108c7565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600e545f90156124ed576064600e5484612106919061348a565b61211091906134a1565b90508060135f8282546121239190613364565b9091555050600a5460ff16801561213b5750600b5415155b156122d157600b545f9061214f90836134a1565b90505f5b600b548110156122ca575f805b60015481101561226357600b838154811061217d5761217d61323d565b5f91825260209091200154600180546001600160a01b0390921691839081106121a8576121a861323d565b5f9182526020909120600360069092020101546001600160a01b03160361225b5783600182815481106121dd576121dd61323d565b905f5260205f2090600602016004015f8282546121fa9190613364565b909155505060075460018054839081106122165761221661323d565b905f5260205f209060060201600401541061225257612252600182815481106122415761224161323d565b905f5260205f20906006020161251f565b60019150612263565b600101612160565b50806122c15760405162461bcd60e51b815260206004820152602760248201527f546172676574204c502070616972206e6f7420666f756e6420696e20706169726044820152667320617272617960c81b60648201526084016108c7565b50600101612153565b50506124ed565b5f82600184516122e19190613425565b815181106122f1576122f161323d565b60200260200101515f8151811061230a5761230a61323d565b602002602001015190505f83600185516123249190613425565b815181106123345761233461323d565b602002602001015160018151811061234e5761234e61323d565b602002602001015190505f5f90505b6001548110156124e957826001600160a01b0316600182815481106123845761238461323d565b5f9182526020909120600690910201546001600160a01b03161480156123e05750816001600160a01b0316600182815481106123c2576123c261323d565b5f9182526020909120600160069092020101546001600160a01b0316145b8061245f5750816001600160a01b0316600182815481106124035761240361323d565b5f9182526020909120600690910201546001600160a01b031614801561245f5750826001600160a01b0316600182815481106124415761244161323d565b5f9182526020909120600160069092020101546001600160a01b0316145b156124e15783600182815481106124785761247861323d565b905f5260205f2090600602016004015f8282546124959190613364565b909155505060075460018054839081106124b1576124b161323d565b905f5260205f20906006020160040154106124dc576124dc600182815481106122415761224161323d565b6124e9565b60010161235d565b5050505b6124f78184613425565b60155f8282546125079190613364565b90915550506008546015541061125d5761125d612975565b6004810180545f918290556005830180549192839261253f908490613364565b90915550506002820154825460018401546005546001600160a01b039384169392831692918216915f9116831461257757818361257a565b82825b6005546040516370a0823160e01b81523060048201529193505f92506001600160a01b0316906370a0823190602401602060405180830381865afa1580156125c4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125e89190613438565b90505f861180156125f95750858110155b1561296c575f61260a6002886134a1565b6040805160028082526060820183529293505f929091602083019080368337505060055482519293506001600160a01b0316918391505f9061264e5761264e61323d565b60200260200101906001600160a01b031690816001600160a01b03168152505083816001815181106126825761268261323d565b6001600160a01b0392831660209182029290920101526040516370a0823160e01b81523060048201525f918616906370a0823190602401602060405180830381865afa1580156126d4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126f89190613438565b604051635c11d79560e01b81529091506001600160a01b03891690635c11d7959061272f9086905f9087903090429060040161344f565b5f604051808303815f87803b158015612746575f5ffd5b505af1158015612758573d5f5f3e3d5ffd5b50506040516370a0823160e01b81523060048201525f92508391506001600160a01b038816906370a0823190602401602060405180830381865afa1580156127a2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127c69190613438565b6127d09190613425565b6005549091505f9081906001600160a01b03808d169163e8e3370091168a898786806128035f546001600160a01b031690565b60405160e089901b6001600160e01b03191681526001600160a01b039788166004820152958716602487015260448601949094526064850192909252608484015260a483015290911660c48201524260e4820152610104016060604051808303815f875af1158015612877573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061289b91906134c0565b5091509150818611156128cf575f6128b38388613425565b9050808e6004015f8282546128c89190613364565b9091555050505b80831115612965575f6128e28285613425565b9050886001600160a01b031663a9059cbb6129045f546001600160a01b031690565b836040518363ffffffff1660e01b81526004016129229291906132d6565b6020604051808303815f875af115801561293e573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061296291906132ef565b50505b5050505050505b50505050505050565b5f600e5460646129859190613425565b600c54601554612995919061348a565b61299f91906134a1565b90505f600e5460646129b19190613425565b600d546015546129c1919061348a565b6129cb91906134a1565b90505f600e5460646129dd9190613425565b600f546015546129ed919061348a565b6129f791906134a1565b90508215612a8d5760055460035460405163a9059cbb60e01b81526001600160a01b039283169263a9059cbb92612a359291169087906004016132d6565b6020604051808303815f875af1158015612a51573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a7591906132ef565b508260125f828254612a879190613364565b90915550505b8115612b21576005546004805460405163a9059cbb60e01b81526001600160a01b039384169363a9059cbb93612ac993909116918791016132d6565b6020604051808303815f875af1158015612ae5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b0991906132ef565b508160115f828254612b1b9190613364565b90915550505b8015612c27576040805160028082526060820183525f92602083019080368337505060055482519293506001600160a01b0316918391505f90612b6657612b6661323d565b6001600160a01b039283166020918202929092010152600654825191169082906001908110612b9757612b9761323d565b6001600160a01b03928316602091820292909201015260175460105460405163791ac94760e01b81529183169263791ac94792612be29287925f92889290911690429060040161344f565b5f604051808303815f87803b158015612bf9575f5ffd5b505af1158015612c0b573d5f5f3e3d5ffd5b505050508160145f828254612c209190613364565b9091555050505b50505f60155550565b828054828255905f5260205f20908101928215612c81579160200282015b82811115612c815781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190612c4e565b50612c8d929150612c91565b5090565b5b80821115612c8d575f8155600101612c92565b5f8151808452602084019350602083015f5b82811015612cde5781516001600160a01b0316865260209586019590910190600101612cb7565b5093949350505050565b602081525f612cfa6020830184612ca5565b9392505050565b5f60208284031215612d11575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715612d5457612d54612d18565b604052919050565b5f6001600160401b03821115612d7457612d74612d18565b5060051b60200190565b80356001600160a01b0381168114612d94575f5ffd5b919050565b5f82601f830112612da8575f5ffd5b8135612dbb612db682612d5c565b612d2c565b8082825260208201915060208360051b860101925085831115612ddc575f5ffd5b602085015b83811015612e0057612df281612d7e565b835260209283019201612de1565b5095945050505050565b5f60208284031215612e1a575f5ffd5b81356001600160401b03811115612e2f575f5ffd5b612e3b84828501612d99565b949350505050565b5f8151808452602084019350602083015f5b82811015612cde578151865260209586019590910190600101612e55565b604081525f612e856040830185612e43565b8281036020840152612e978185612e43565b95945050505050565b5f5f5f5f60808587031215612eb3575f5ffd5b612ebc85612d7e565b9350612eca60208601612d7e565b9250612ed860408601612d7e565b9150612ee660608601612d7e565b905092959194509250565b5f60208284031215612f01575f5ffd5b612cfa82612d7e565b602080825282518282018190525f918401906040840190835b81811015612f8d57835180516001600160a01b039081168552602080830151821681870152604080840151831690870152606080840151909216918601919091526080808301519086015260a091820151918501919091529093019260c090920191600101612f23565b509095945050505050565b8015158114612041575f5ffd5b5f5f5f60408486031215612fb7575f5ffd5b83356001600160401b03811115612fcc575f5ffd5b8401601f81018613612fdc575f5ffd5b80356001600160401b03811115612ff1575f5ffd5b8660208260051b8401011115613005575f5ffd5b60209182019450925084013561301a81612f98565b809150509250925092565b5f5f5f5f5f60a08688031215613039575f5ffd5b505083359560208501359550604085013594606081013594506080013592509050565b5f5f6040838503121561306d575f5ffd5b61307683612d7e565b946020939093013593505050565b5f82601f830112613093575f5ffd5b81356130a1612db682612d5c565b8082825260208201915060208360051b8601019250858311156130c2575f5ffd5b602085015b83811015612e005780358352602092830192016130c7565b5f82601f8301126130ee575f5ffd5b81356130fc612db682612d5c565b8082825260208201915060208360051b86010192508583111561311d575f5ffd5b602085015b83811015612e005780356001600160401b0381111561313f575f5ffd5b61314e886020838a0101612d99565b84525060209283019201613122565b5f5f6040838503121561316e575f5ffd5b82356001600160401b03811115613183575f5ffd5b61318f85828601613084565b92505060208301356001600160401b038111156131aa575f5ffd5b6131b6858286016130df565b9150509250929050565b602081525f612cfa6020830184612e43565b5f5f5f606084860312156131e4575f5ffd5b83356001600160401b038111156131f9575f5ffd5b613205868287016130df565b9350506020840135915060408401356001600160401b03811115613227575f5ffd5b61323386828701613084565b9150509250925092565b634e487b7160e01b5f52603260045260245ffd5b602080825260149082015273496e76616c69642070616972206164647265737360601b604082015260600190565b80516001600160701b0381168114612d94575f5ffd5b5f5f5f606084860312156132a7575f5ffd5b6132b08461327f565b92506132be6020850161327f565b9150604084015163ffffffff8116811461301a575f5ffd5b6001600160a01b03929092168252602082015260400190565b5f602082840312156132ff575f5ffd5b8151612cfa81612f98565b60208082526026908201527f43616e6e6f7420736574206d6f7265207468616e2034204c502074617267657460408201526520706169727360d01b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561337757613377613350565b92915050565b828152604060208201525f612e3b6040830184612ca5565b5f602082840312156133a5575f5ffd5b81516001600160401b038111156133ba575f5ffd5b8201601f810184136133ca575f5ffd5b80516133d8612db682612d5c565b8082825260208201915060208360051b8501019250868311156133f9575f5ffd5b6020840193505b8284101561341b578351825260209384019390910190613400565b9695505050505050565b8181038181111561337757613377613350565b5f60208284031215613448575f5ffd5b5051919050565b85815284602082015260a060408201525f61346d60a0830186612ca5565b6001600160a01b0394909416606083015250608001529392505050565b808202811582820484141761337757613377613350565b5f826134bb57634e487b7160e01b5f52601260045260245ffd5b500490565b5f5f5f606084860312156134d2575f5ffd5b505081516020830151604090930151909492935091905056fea264697066735822122005febe6a461ba76c0b80b47428d855c536521aaaa0253f7647fa59a6707e707d64736f6c634300081b0033