ETH Price: $2,628.13 (+5.83%)
Gas: 5 Gwei

Contract

0xe6e462d72350d3cC49090eeFCBc51a30c782c1Ea
 

Overview

ETH Balance

0.250528840144330457 ETH

Eth Value

$658.42 (@ $2,628.13/ETH)

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Emergency Withdr...146048162022-04-17 20:09:15844 days ago1650226155IN
0xe6e462d7...0c782c1Ea
0 ETH0.0023708333.08638338
Emergency Withdr...144792612022-03-29 5:38:10864 days ago1648532290IN
0xe6e462d7...0c782c1Ea
0 ETH0.0025475236.69945276
Deposit Koro LP ...144657452022-03-27 3:09:20866 days ago1648350560IN
0xe6e462d7...0c782c1Ea
0 ETH0.0053884821.01634106
Emergency Withdr...144376692022-03-22 18:16:09870 days ago1647972969IN
0xe6e462d7...0c782c1Ea
0 ETH0.0064992693.62776892
Emergency Withdr...144285732022-03-21 8:12:57872 days ago1647850377IN
0xe6e462d7...0c782c1Ea
0 ETH0.0013070718.82962872
Emergency Withdr...143396502022-03-07 12:16:35886 days ago1646655395IN
0xe6e462d7...0c782c1Ea
0 ETH0.0018137225.31157457
Emergency Withdr...143305502022-03-06 2:04:44887 days ago1646532284IN
0xe6e462d7...0c782c1Ea
0 ETH0.0012912118.60111453
Emergency Withdr...143090542022-03-02 17:47:25890 days ago1646243245IN
0xe6e462d7...0c782c1Ea
0 ETH0.0049271770.98043397
Emergency Withdr...143054292022-03-02 4:26:22891 days ago1646195182IN
0xe6e462d7...0c782c1Ea
0 ETH0.0021686843.31384821
Emergency Withdr...143054292022-03-02 4:26:22891 days ago1646195182IN
0xe6e462d7...0c782c1Ea
0 ETH0.0030066743.31384821
Emergency Withdr...143030772022-03-01 19:45:39891 days ago1646163939IN
0xe6e462d7...0c782c1Ea
0 ETH0.0036061151.94940089
Harvest143030432022-03-01 19:39:09891 days ago1646163549IN
0xe6e462d7...0c782c1Ea
0 ETH0.0108974457.09952983
Emergency Withdr...142995342022-03-01 6:45:33892 days ago1646117133IN
0xe6e462d7...0c782c1Ea
0 ETH0.0035587351.26682347
Emergency Withdr...142961732022-02-28 18:12:06892 days ago1646071926IN
0xe6e462d7...0c782c1Ea
0 ETH0.00717361103.34232885
Emergency Withdr...142954912022-02-28 15:37:54892 days ago1646062674IN
0xe6e462d7...0c782c1Ea
0 ETH0.0053247576.70787238
Emergency Withdr...142952382022-02-28 14:42:34892 days ago1646059354IN
0xe6e462d7...0c782c1Ea
0 ETH0.0031008844.67109351
Emergency Withdr...142939512022-02-28 9:59:25893 days ago1646042365IN
0xe6e462d7...0c782c1Ea
0 ETH0.0020947228.34688249
Emergency Withdr...142939172022-02-28 9:52:44893 days ago1646041964IN
0xe6e462d7...0c782c1Ea
0 ETH0.0032751947.18207445
Harvest142932832022-02-28 7:29:17893 days ago1646033357IN
0xe6e462d7...0c782c1Ea
0 ETH0.0067331535.27983019
Emergency Withdr...142930502022-02-28 6:40:39893 days ago1646030439IN
0xe6e462d7...0c782c1Ea
0 ETH0.0024411135.1665319
Emergency Withdr...142920312022-02-28 2:51:00893 days ago1646016660IN
0xe6e462d7...0c782c1Ea
0 ETH0.0050542472.81088171
Emergency Withdr...142920172022-02-28 2:47:50893 days ago1646016470IN
0xe6e462d7...0c782c1Ea
0 ETH0.0052457473.20727504
Harvest142919142022-02-28 2:20:37893 days ago1646014837IN
0xe6e462d7...0c782c1Ea
0 ETH0.0213081839.79698487
Emergency Withdr...142909392022-02-27 22:30:49893 days ago1646001049IN
0xe6e462d7...0c782c1Ea
0 ETH0.0050284390.2188848
Emergency Withdr...142904242022-02-27 20:32:46893 days ago1645993966IN
0xe6e462d7...0c782c1Ea
0 ETH0.003462949.88630033
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
142919142022-02-28 2:20:37893 days ago1646014837
0xe6e462d7...0c782c1Ea
0.0000014 ETH
142904132022-02-27 20:31:00893 days ago1645993860
0xe6e462d7...0c782c1Ea
0.00003317 ETH
142867322022-02-27 6:56:23894 days ago1645944983
0xe6e462d7...0c782c1Ea
0.00001617 ETH
142857082022-02-27 3:01:39894 days ago1645930899
0xe6e462d7...0c782c1Ea
0.00002232 ETH
142856662022-02-27 2:53:35894 days ago1645930415
0xe6e462d7...0c782c1Ea
0.00000393 ETH
142854832022-02-27 2:15:45894 days ago1645928145
0xe6e462d7...0c782c1Ea
0.00000191 ETH
142828612022-02-26 16:45:15894 days ago1645893915
0xe6e462d7...0c782c1Ea
0.00000997 ETH
142826062022-02-26 15:49:40894 days ago1645890580
0xe6e462d7...0c782c1Ea
0.00004074 ETH
142824502022-02-26 15:14:56894 days ago1645888496
0xe6e462d7...0c782c1Ea
0.00004742 ETH
142802502022-02-26 7:08:49895 days ago1645859329
0xe6e462d7...0c782c1Ea
0.00002729 ETH
142761852022-02-25 15:49:32895 days ago1645804172
0xe6e462d7...0c782c1Ea
0.00001234 ETH
142757312022-02-25 14:14:25895 days ago1645798465
0xe6e462d7...0c782c1Ea
0.00001384 ETH
142748022022-02-25 10:52:44896 days ago1645786364
0xe6e462d7...0c782c1Ea
0.00054026 ETH
142747872022-02-25 10:48:46896 days ago1645786126
0xe6e462d7...0c782c1Ea
0.00001412 ETH
142721322022-02-25 0:37:23896 days ago1645749443
0xe6e462d7...0c782c1Ea
0.00001368 ETH
142677202022-02-24 8:28:00897 days ago1645691280
0xe6e462d7...0c782c1Ea
0.00002968 ETH
142613832022-02-23 8:56:29898 days ago1645606589
0xe6e462d7...0c782c1Ea
0.00005164 ETH
142608322022-02-23 6:50:12898 days ago1645599012
0xe6e462d7...0c782c1Ea
0.00001919 ETH
142608322022-02-23 6:50:12898 days ago1645599012
0xe6e462d7...0c782c1Ea
1 wei
142605692022-02-23 5:48:05898 days ago1645595285
0xe6e462d7...0c782c1Ea
0.00004118 ETH
142573412022-02-22 17:58:07898 days ago1645552687
0xe6e462d7...0c782c1Ea
0.00005504 ETH
142573412022-02-22 17:58:07898 days ago1645552687
0xe6e462d7...0c782c1Ea
1 wei
142550872022-02-22 9:38:49899 days ago1645522729
0xe6e462d7...0c782c1Ea
0.0000246 ETH
142550872022-02-22 9:38:49899 days ago1645522729
0xe6e462d7...0c782c1Ea
1 wei
142550402022-02-22 9:28:20899 days ago1645522100
0xe6e462d7...0c782c1Ea
0.00000801 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
KoroFarms

Compiler Version
v0.8.8+commit.dddeac2f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 11 : KoroFarms.sol
// SPDX-License-Identifier: GPL-2.0
pragma solidity 0.8.8;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

interface IWETH {
    function deposit() external payable;

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

    function withdraw(uint256) external;
}

interface IUniswapV2Factory {
    function getPair(address tokenA, address tokenB)
        external
        view
        returns (address);
}

interface IUniswapV2Pair {
    function token0() external pure returns (address);

    function token1() external pure returns (address);

    function getReserves()
        external
        view
        returns (
            uint112 _reserve0,
            uint112 _reserve1,
            uint32 _blockTimestampLast
        );
}

interface IUniswapV2Router02 {
    function factory() external pure returns (address);

    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    )
        external
        returns (
            uint256 amountA,
            uint256 amountB,
            uint256 liquidity
        );

    function addLiquidityETH(
        address token,
        uint256 amountTokenDesired,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    )
        external
        payable
        returns (
            uint256 amountToken,
            uint256 amountETH,
            uint256 liquidity
        );

    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountA, uint256 amountB);

    function removeLiquidityETH(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountToken, uint256 amountETH);

    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint256 liquidity,
        uint256 amountAMin,
        uint256 amountBMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountA, uint256 amountB);

    function removeLiquidityETHWithPermit(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountToken, uint256 amountETH);

    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapTokensForExactTokens(
        uint256 amountOut,
        uint256 amountInMax,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapExactETHForTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint256[] memory amounts);

    function swapTokensForExactETH(
        uint256 amountOut,
        uint256 amountInMax,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapExactTokensForETH(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapETHForExactTokens(
        uint256 amountOut,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint256[] memory amounts);

    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external returns (uint256 amountETH);

    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint256 liquidity,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external returns (uint256 amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;

    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable;

    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;

    function quote(
        uint256 amountA,
        uint256 reserveA,
        uint256 reserveB
    ) external pure returns (uint256 amountB);

    function getAmountOut(
        uint256 amountIn,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountOut);

    function getAmountIn(
        uint256 amountOut,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountIn);

    function getAmountsOut(uint256 amountIn, address[] calldata path)
        external
        view
        returns (uint256[] memory amounts);

    function getAmountsIn(uint256 amountOut, address[] calldata path)
        external
        view
        returns (uint256[] memory amounts);
}

abstract contract Zap {
    using SafeERC20 for IERC20;
    using SafeMath for uint256;

    IERC20 public immutable koromaru; // Koromaru token
    IERC20 public immutable koromaruUniV2; // Uniswap V2 LP token for Koromaru

    IUniswapV2Factory public immutable UniSwapV2FactoryAddress;
    IUniswapV2Router02 public uniswapRouter;
    address public immutable WETHAddress;

    uint256 private constant swapDeadline =
        0xf000000000000000000000000000000000000000000000000000000000000000;

    struct ZapVariables {
        uint256 LP;
        uint256 koroAmount;
        uint256 wethAmount;
        address tokenToZap;
        uint256 amountToZap;
    }

    event ZappedIn(address indexed account, uint256 amount);
    event ZappedOut(
        address indexed account,
        uint256 amount,
        uint256 koroAmount,
        uint256 Eth
    );

    constructor(
        address _koromaru,
        address _koromaruUniV2,
        address _UniSwapV2FactoryAddress,
        address _uniswapRouter
    ) {
        koromaru = IERC20(_koromaru);
        koromaruUniV2 = IERC20(_koromaruUniV2);

        UniSwapV2FactoryAddress = IUniswapV2Factory(_UniSwapV2FactoryAddress);
        uniswapRouter = IUniswapV2Router02(_uniswapRouter);

        WETHAddress = uniswapRouter.WETH();
    }

    function ZapIn(uint256 _amount, bool _multi)
        internal
        returns (
            uint256 _LP,
            uint256 _WETHBalance,
            uint256 _KoromaruBalance
        )
    {
        (uint256 _koroAmount, uint256 _ethAmount) = _moveTokensToContract(
            _amount
        );
        _approveRouterIfNotApproved();

        (_LP, _WETHBalance, _KoromaruBalance) = !_multi
            ? _zapIn(_koroAmount, _ethAmount)
            : _zapInMulti(_koroAmount, _ethAmount);
        require(_LP > 0, "ZapIn: Invalid LP amount");

        emit ZappedIn(msg.sender, _LP);
    }

    function zapOut(uint256 _koroLPAmount)
        internal
        returns (uint256 _koroTokens, uint256 _ether)
    {
        _approveRouterIfNotApproved();

        uint256 balanceBefore = koromaru.balanceOf(address(this));
        _ether = uniswapRouter.removeLiquidityETHSupportingFeeOnTransferTokens(
            address(koromaru),
            _koroLPAmount,
            1,
            1,
            address(this),
            swapDeadline
        );
        require(_ether > 0, "ZapOut: Eth Output Low");

        uint256 balanceAfter = koromaru.balanceOf(address(this));
        require(balanceAfter > balanceBefore, "ZapOut: Nothing to ZapOut");
        _koroTokens = balanceAfter.sub(balanceBefore);

        emit ZappedOut(msg.sender, _koroLPAmount, _koroTokens, _ether);
    }

    //-------------------- Zap Utils -------------------------
    function _zapIn(uint256 _koroAmount, uint256 _wethAmount)
        internal
        returns (
            uint256 _LP,
            uint256 _WETHBalance,
            uint256 _KoromaruBalance
        )
    {
        ZapVariables memory zapVars;

        zapVars.tokenToZap; // koro or eth
        zapVars.amountToZap; // koro or weth

        (address _Token0, address _Token1) = _getKoroLPPairs(
            address(koromaruUniV2)
        );

        if (_koroAmount > 0 && _wethAmount < 1) {
            // if only koro
            zapVars.amountToZap = _koroAmount;
            zapVars.tokenToZap = address(koromaru);
        } else if (_wethAmount > 0 && _koroAmount < 1) {
            // if only weth
            zapVars.amountToZap = _wethAmount;
            zapVars.tokenToZap = WETHAddress;
        }

        (uint256 token0Out, uint256 token1Out) = _executeSwapForPairs(
            zapVars.tokenToZap,
            _Token0,
            _Token1,
            zapVars.amountToZap
        );

        (_LP, _WETHBalance, _KoromaruBalance) = _toLiquidity(
            _Token0,
            _Token1,
            token0Out,
            token1Out
        );
    }

    function _zapInMulti(uint256 _koroAmount, uint256 _wethAmount)
        internal
        returns (
            uint256 _LPToken,
            uint256 _WETHBalance,
            uint256 _KoromaruBalance
        )
    {
        ZapVariables memory zapVars;

        zapVars.koroAmount = _koroAmount;
        zapVars.wethAmount = _wethAmount;

        zapVars.tokenToZap; // koro or eth
        zapVars.amountToZap; // koro or weth

        {
            (
                uint256 _kLP,
                uint256 _kWETHBalance,
                uint256 _kKoromaruBalance
            ) = _zapIn(zapVars.koroAmount, 0);
            _LPToken += _kLP;
            _WETHBalance += _kWETHBalance;
            _KoromaruBalance += _kKoromaruBalance;
        }
        {
            (
                uint256 _kLP,
                uint256 _kWETHBalance,
                uint256 _kKoromaruBalance
            ) = _zapIn(0, zapVars.wethAmount);
            _LPToken += _kLP;
            _WETHBalance += _kWETHBalance;
            _KoromaruBalance += _kKoromaruBalance;
        }
    }

    function _toLiquidity(
        address _Token0,
        address _Token1,
        uint256 token0Out,
        uint256 token1Out
    )
        internal
        returns (
            uint256 _LP,
            uint256 _WETHBalance,
            uint256 _KoromaruBalance
        )
    {
        _approveToken(_Token0, address(uniswapRouter), token0Out);
        _approveToken(_Token1, address(uniswapRouter), token1Out);

        (uint256 amountA, uint256 amountB, uint256 LP) = uniswapRouter
            .addLiquidity(
                _Token0,
                _Token1,
                token0Out,
                token1Out,
                1,
                1,
                address(this),
                swapDeadline
            );

        _LP = LP;
        _WETHBalance = token0Out.sub(amountA);
        _KoromaruBalance = token1Out.sub(amountB);
    }

    function _approveRouterIfNotApproved() private {
        if (koromaru.allowance(address(this), address(uniswapRouter)) == 0) {
            koromaru.approve(address(uniswapRouter), type(uint256).max);
        }

        if (
            koromaruUniV2.allowance(address(this), address(uniswapRouter)) == 0
        ) {
            koromaruUniV2.approve(address(uniswapRouter), type(uint256).max);
        }
    }

    function _moveTokensToContract(uint256 _amount)
        internal
        returns (uint256 _koroAmount, uint256 _ethAmount)
    {
        _ethAmount = msg.value;

        if (msg.value > 0) IWETH(WETHAddress).deposit{value: _ethAmount}();

        if (msg.value < 1) {
            // ZapIn must have either both Koro and Eth, just Eth or just Koro
            require(_amount > 0, "KOROFARM: Invalid ZapIn Call");
        }

        if (_amount > 0) {
            koromaru.safeTransferFrom(msg.sender, address(this), _amount);
        }

        _koroAmount = _amount;
    }

    function _getKoroLPPairs(address _pairAddress)
        internal
        pure
        returns (address token0, address token1)
    {
        IUniswapV2Pair uniPair = IUniswapV2Pair(_pairAddress);
        token0 = uniPair.token0();
        token1 = uniPair.token1();
    }

    function _executeSwapForPairs(
        address _inToken,
        address _token0,
        address _token1,
        uint256 _amount
    ) internal returns (uint256 _token0Out, uint256 _token1Out) {
        IUniswapV2Pair koroPair = IUniswapV2Pair(address(koromaruUniV2));

        (uint256 resv0, uint256 resv1, ) = koroPair.getReserves();

        if (_inToken == _token0) {
            uint256 swapAmount = determineSwapInAmount(resv0, _amount);
            if (swapAmount < 1) swapAmount = _amount.div(2);
            // swap Weth tokens to koro
            _token1Out = _swapTokenForToken(_inToken, _token1, swapAmount);
            _token0Out = _amount.sub(swapAmount);
        } else {
            uint256 swapAmount = determineSwapInAmount(resv1, _amount);
            if (swapAmount < 1) swapAmount = _amount.div(2);
            _token0Out = _swapTokenForToken(_inToken, _token0, swapAmount);
            _token1Out = _amount.sub(swapAmount);
        }
    }

    function _swapTokenForToken(
        address _swapFrom,
        address _swapTo,
        uint256 _tokensToSwap
    ) internal returns (uint256 tokenBought) {
        if (_swapFrom == _swapTo) {
            return _tokensToSwap;
        }

        _approveToken(
            _swapFrom,
            address(uniswapRouter),
            _tokensToSwap.mul(1e12)
        );

        address pair = UniSwapV2FactoryAddress.getPair(_swapFrom, _swapTo);

        require(pair != address(0), "SwapTokenForToken: Swap path error");
        address[] memory path = new address[](2);
        path[0] = _swapFrom;
        path[1] = _swapTo;

        uint256 balanceBefore = IERC20(_swapTo).balanceOf(address(this));
        uniswapRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            _tokensToSwap,
            0,
            path,
            address(this),
            swapDeadline
        );
        uint256 balanceAfter = IERC20(_swapTo).balanceOf(address(this));

        tokenBought = balanceAfter.sub(balanceBefore);

        // Ideal, but fails to work with Koromary due to fees
        // tokenBought = uniswapRouter.swapExactTokensForTokens(
        //     _tokensToSwap,
        //     1,
        //     path,
        //     address(this),
        //     swapDeadline
        // )[path.length - 1];
        // }

        require(tokenBought > 0, "SwapTokenForToken: Error Swapping Tokens 2");
    }

    function determineSwapInAmount(uint256 _pairResIn, uint256 _userAmountIn)
        internal
        pure
        returns (uint256)
    {
        return
            (_sqrt(
                _pairResIn *
                    ((_userAmountIn * 3988000) + (_pairResIn * 3988009))
            ) - (_pairResIn * 1997)) / 1994;
    }

    function _sqrt(uint256 _val) internal pure returns (uint256 z) {
        if (_val > 3) {
            z = _val;
            uint256 x = _val / 2 + 1;
            while (x < z) {
                z = x;
                x = (_val / x + x) / 2;
            }
        } else if (_val != 0) {
            z = 1;
        }
    }

    function _approveToken(
        address token,
        address spender,
        uint256 amount
    ) internal {
        IERC20 _token = IERC20(token);
        _token.safeApprove(spender, 0);
        _token.safeApprove(spender, amount);
    }

    //---------------- End of Zap Utils ----------------------
}

contract KoroFarms is Ownable, Pausable, ReentrancyGuard, Zap {
    using SafeERC20 for IERC20;
    using SafeMath for uint256;
    using EnumerableSet for EnumerableSet.AddressSet;

    struct UserInfo {
        uint256 amount;
        uint256 koroDebt;
        uint256 ethDebt;
        uint256 unpaidKoro;
        uint256 unpaidEth;
        uint256 lastRewardHarvestedTime;
    }

    struct FarmInfo {
        uint256 accKoroRewardsPerShare;
        uint256 accEthRewardsPerShare;
        uint256 lastRewardTimestamp;
    }

    AggregatorV3Interface internal priceFeed;
    uint256 internal immutable koromaruDecimals;
    uint256 internal constant EthPriceFeedDecimal = 1e8;
    uint256 internal constant precisionScaleUp = 1e30;
    uint256 internal constant secsPerDay = 1 days / 1 seconds;
    uint256 private taxRefundPercentage;
    uint256 internal constant _1hundred_Percent = 10000;
    uint256 public APR; // 100% = 10000, 50% = 5000, 15% = 1500
    uint256 rewardHarvestingInterval;
    uint256 public koroRewardAllocation;
    uint256 public ethRewardAllocation;
    uint256 internal maxLPLimit;
    uint256 internal zapKoroLimit;

    FarmInfo public farmInfo;
    mapping(address => UserInfo) public userInfo;

    uint256 public totalEthRewarded; // total amount of eth given as rewards
    uint256 public totalKoroRewarded; // total amount of Koro given as rewards

    //---------------- Contract Events -------------------

    event Compound(address indexed account, uint256 koro, uint256 eth);
    event Withdraw(address indexed account, uint256 amount);
    event Deposit(address indexed account, uint256 amount);
    event EmergencyWithdraw(address indexed user, uint256 amount);
    event KoroRewardsHarvested(address indexed account, uint256 Kororewards);
    event EthRewardsHarvested(address indexed account, uint256 Ethrewards);
    event APRUpdated(uint256 OldAPR, uint256 NewAPR);
    event Paused();
    event Unpaused();
    event IncreaseKoroRewardPool(uint256 amount);
    event IncreaseEthRewardPool(uint256 amount);

    //------------- End of Contract Events ----------------

    constructor(
        address _koromaru,
        address _koromaruUniV2,
        address _UniSwapV2FactoryAddress,
        address _uniswapRouter,
        uint256 _apr,
        uint256 _taxToRefund,
        uint256 _koromaruTokenDecimals,
        uint256 _koroRewardAllocation,
        uint256 _rewardHarvestingInterval,
        uint256 _zapKoroLimit
    ) Zap(_koromaru, _koromaruUniV2, _UniSwapV2FactoryAddress, _uniswapRouter) {
        require(
            _koroRewardAllocation <= 10000,
            "setRewardAllocations: Invalid rewards allocation"
        );
        require(_apr <= 10000, "SetDailyAPR: Invalid APR Value");

        approveRouterIfNotApproved();

        koromaruDecimals = 10**_koromaruTokenDecimals;
        zapKoroLimit = _zapKoroLimit * 10**_koromaruTokenDecimals;
        APR = _apr;
        koroRewardAllocation = _koroRewardAllocation;
        ethRewardAllocation = _1hundred_Percent.sub(_koroRewardAllocation);
        taxRefundPercentage = _taxToRefund;

        farmInfo = FarmInfo({
            lastRewardTimestamp: block.timestamp,
            accKoroRewardsPerShare: 0,
            accEthRewardsPerShare: 0
        });

        rewardHarvestingInterval = _rewardHarvestingInterval * 1 seconds;
        priceFeed = AggregatorV3Interface(
            0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419
        );
    }

    //---------------- Contract Owner  ----------------------
    /**
     * @notice Update chainLink Eth Price feed
     */
    function updatePriceFeed(address _usdt_eth_aggregator) external onlyOwner {
        priceFeed = AggregatorV3Interface(_usdt_eth_aggregator);
    }

    /**
     * @notice Set's tax refund percentage for Koromaru
     * @dev User 100% = 10000, 50% = 5000, 15% = 1500 etc.
     */
    function setTaxRefundPercent(uint256 _taxToRefund) external onlyOwner {
        taxRefundPercentage = _taxToRefund;
    }

    /**
     * @notice Set's max koromaru per transaction
     * @dev Decimals will be added automatically
     */
    function setZapLimit(uint256 _limit) external onlyOwner {
        zapKoroLimit = _limit * koromaruDecimals;
    }

    /**
     * @notice Set's daily ROI percentage for the farm
     * @dev User 100% = 10000, 50% = 5000, 15% = 1500 etc.
     */
    function setDailyAPR(uint256 _dailyAPR) external onlyOwner {
        updateFarm();
        require(_dailyAPR <= 10000, "SetDailyAPR: Invalid APR Value");
        uint256 oldAPr = APR;
        APR = _dailyAPR;
        emit APRUpdated(oldAPr, APR);
    }

    /**
     * @notice Set's reward allocation for reward pool
     * @dev Set for Koromaru only, eth's allocation will be calcuated. User 100% = 10000, 50% = 5000, 15% = 1500 etc.
     */
    function setRewardAllocations(uint256 _koroAllocation) external onlyOwner {
        // setting 10000 (100%) will set eth rewards to 0.
        require(
            _koroAllocation <= 10000,
            "setRewardAllocations: Invalid rewards allocation"
        );
        koroRewardAllocation = _koroAllocation;
        ethRewardAllocation = _1hundred_Percent.sub(_koroAllocation);
    }

    /**
     * @notice Set's maximum amount of LPs that can be staked in this farm
     * @dev When 0, no limit is imposed. When max is reached farmers cannot stake more LPs or compound.
     */
    function setMaxLPLimit(uint256 _maxLPLimit) external onlyOwner {
        // A new user’s stake cannot cause the amount of LP tokens in the farm to exceed this value
        // MaxLP can be set to 0(nomax)
        maxLPLimit = _maxLPLimit;
    }

    /**
     * @notice Reset's the chainLink price feed to the default price feed
     */
    function resetPriceFeed() external onlyOwner {
        priceFeed = AggregatorV3Interface(
            0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419
        );
    }

    /**
     * @notice Withdraw foreign tokens sent to this contract
     * @dev Can only withdraw none koromaru tokens and KoroV2 tokens
     */
    function withdrawForeignToken(address _token)
        external
        nonReentrant
        onlyOwner
    {
        require(_token != address(0), "KOROFARM: Invalid Token");
        require(
            _token != address(koromaru),
            "KOROFARM: Token cannot be same as koromaru tokens"
        );
        require(
            _token != address(koromaruUniV2),
            "KOROFARM: Token cannot be same as farmed tokens"
        );

        uint256 amount = IERC20(_token).balanceOf(address(this));
        if (amount > 0) {
            IERC20(_token).safeTransfer(msg.sender, amount);
        }
    }

    /**
     * @notice Deposit Koromaru tokens into reward pool
     */
    function depositKoroRewards(uint256 _amount)
        external
        onlyOwner
        nonReentrant
    {
        require(_amount > 0, "KOROFARM: Invalid Koro Amount");

        koromaru.safeTransferFrom(msg.sender, address(this), _amount);
        emit IncreaseKoroRewardPool(_amount);
    }

    /**
     * @notice Deposit Eth tokens into reward pool
     */
    function depositEthRewards() external payable onlyOwner nonReentrant {
        require(msg.value > 0, "KOROFARM: Invalid Eth Amount");
        emit IncreaseEthRewardPool(msg.value);
    }

    /**
     * @notice This function will pause the farm and withdraw all rewards in case of failure or emergency
     */
    function pauseAndRemoveRewardPools() external onlyOwner whenNotPaused {
        // only to be used by admin in critical situations
        uint256 koroBalance = koromaru.balanceOf(address(this));
        uint256 ethBalance = payable(address(this)).balance;
        if (koroBalance > 0) {
            koromaru.safeTransfer(msg.sender, koroBalance);
        }

        if (ethBalance > 0) {
            (bool sent, ) = payable(msg.sender).call{value: ethBalance}("");
            require(sent, "Failed to send Ether");
        }
    }

    /**
     * @notice Initiate stopped state
     * @dev Only possible when contract not paused.
     */
    function pause() external onlyOwner whenNotPaused {
        _pause();
        emit Paused();
    }

    /**
     * @notice Initiate normal state
     * @dev Only possible when contract is paused.
     */
    function unpause() external onlyOwner whenPaused {
        _unpause();
        emit Unpaused();
    }

    //-------------- End Contract Owner  --------------------

    //---------------- Contract Farmer  ----------------------
    /**
     * @notice Calculates and returns pending rewards for a farmer
     */
    function getPendingRewards(address _farmer)
        public
        view
        returns (uint256 pendinKoroTokens, uint256 pendingEthWei)
    {
        UserInfo storage user = userInfo[_farmer];
        uint256 accKoroRewardsPerShare = farmInfo.accKoroRewardsPerShare;
        uint256 accEthRewardsPerShare = farmInfo.accEthRewardsPerShare;
        uint256 stakedTVL = getStakedTVL();

        if (block.timestamp > farmInfo.lastRewardTimestamp && stakedTVL != 0) {
            uint256 timeElapsed = block.timestamp.sub(
                farmInfo.lastRewardTimestamp
            );
            uint256 koroReward = timeElapsed.mul(
                getNumberOfKoroRewardsPerSecond(koroRewardAllocation)
            );
            uint256 ethReward = timeElapsed.mul(
                getAmountOfEthRewardsPerSecond(ethRewardAllocation)
            );

            accKoroRewardsPerShare = accKoroRewardsPerShare.add(
                koroReward.mul(precisionScaleUp).div(stakedTVL)
            );
            accEthRewardsPerShare = accEthRewardsPerShare.add(
                ethReward.mul(precisionScaleUp).div(stakedTVL)
            );
        }

        pendinKoroTokens = user
            .amount
            .mul(accKoroRewardsPerShare)
            .div(precisionScaleUp)
            .sub(user.koroDebt)
            .add(user.unpaidKoro);

        pendingEthWei = user
            .amount
            .mul(accEthRewardsPerShare)
            .div(precisionScaleUp)
            .sub(user.ethDebt)
            .add(user.unpaidEth);
    }

    /**
     * @notice Calculates and returns the TVL in USD staked in the farm
     * @dev Uses the price of 1 Koromaru to calculate the TVL in USD
     */
    function getStakedTVL() public view returns (uint256) {
        uint256 stakedLP = koromaruUniV2.balanceOf(address(this));
        uint256 totalLPsupply = koromaruUniV2.totalSupply();
        return stakedLP.mul(getTVLUsingKoro()).div(totalLPsupply);
    }

    /**
     * @notice Calculates and updates the farm's rewards per share
     * @dev Called by other function to update the function state
     */
    function updateFarm() public whenNotPaused returns (FarmInfo memory farm) {
        farm = farmInfo;

        uint256 WETHBalance = IERC20(WETHAddress).balanceOf(address(this));
        if (WETHBalance > 0) IWETH(WETHAddress).withdraw(WETHBalance);

        if (block.timestamp > farm.lastRewardTimestamp) {
            uint256 stakedTVL = getStakedTVL();

            if (stakedTVL > 0) {
                uint256 timeElapsed = block.timestamp.sub(
                    farm.lastRewardTimestamp
                );
                uint256 koroReward = timeElapsed.mul(
                    getNumberOfKoroRewardsPerSecond(koroRewardAllocation)
                );
                uint256 ethReward = timeElapsed.mul(
                    getAmountOfEthRewardsPerSecond(ethRewardAllocation)
                );
                farm.accKoroRewardsPerShare = farm.accKoroRewardsPerShare.add(
                    (koroReward.mul(precisionScaleUp) / stakedTVL)
                );
                farm.accEthRewardsPerShare = farm.accEthRewardsPerShare.add(
                    (ethReward.mul(precisionScaleUp) / stakedTVL)
                );
            }

            farm.lastRewardTimestamp = block.timestamp;
            farmInfo = farm;
        }
    }

    /**
     * @notice Deposit Koromaru tokens into farm
     * @dev Deposited Koromaru will zap into Koro/WETH LP tokens, a refund of TX fee % will be issued
     */
    function depositKoroTokensOnly(uint256 _amount)
        external
        whenNotPaused
        nonReentrant
    {
        require(_amount > 0, "KOROFARM: Invalid Koro Amount");
        require(
            _amount <= zapKoroLimit,
            "KOROFARM: Can't deposit more than Zap Limit"
        );

        (uint256 lpZappedIn, , ) = ZapIn(_amount, false);

        // do tax refund
        userInfo[msg.sender].unpaidKoro += _amount.mul(taxRefundPercentage).div(
            _1hundred_Percent
        );

        onDeposit(msg.sender, lpZappedIn);
    }

    /**
     * @notice Deposit Koro/WETH LP tokens into farm
     */
    function depositKoroLPTokensOnly(uint256 _amount)
        external
        whenNotPaused
        nonReentrant
    {
        require(_amount > 0, "KOROFARM: Invalid KoroLP Amount");
        koromaruUniV2.safeTransferFrom(msg.sender, address(this), _amount);
        onDeposit(msg.sender, _amount);
    }

    /**
     * @notice Deposit Koromaru, Koromaru/Eth LP and Eth at once into farm requires all 3
     */
    function depositMultipleAssets(uint256 _koro, uint256 _koroLp)
        external
        payable
        whenNotPaused
        nonReentrant
    {
        // require(_koro > 0, "KOROFARM: Invalid Koro Amount");
        // require(_koroLp > 0, "KOROFARM: Invalid LP Amount");
        require(
            _koro <= zapKoroLimit,
            "KOROFARM: Can't deposit more than Zap Limit"
        );

        // execute the zap
        // (uint256 lpZappedIn,uint256 wethBalance, uint256 korobalance)= ZapIn(_koro, true);
        (uint256 lpZappedIn, , ) = msg.value > 0
            ? ZapIn(_koro, true)
            : ZapIn(_koro, false);

        // transfer the lp in
        if (_koroLp > 0)
            koromaruUniV2.safeTransferFrom(
                address(msg.sender),
                address(this),
                _koroLp
            );

        uint256 sumOfLps = lpZappedIn + _koroLp;

        // do tax refund
        userInfo[msg.sender].unpaidKoro += _koro.mul(taxRefundPercentage).div(
            _1hundred_Percent
        );

        onDeposit(msg.sender, sumOfLps);
    }

    /**
     * @notice Deposit Eth only into farm
     * @dev Deposited Eth will zap into Koro/WETH LP tokens
     */
    function depositEthOnly() external payable whenNotPaused nonReentrant {
        require(msg.value > 0, "KOROFARM: Invalid Eth Amount");

        // (uint256 lpZappedIn, uint256 wethBalance, uint256 korobalance)= ZapIn(0, false);
        (uint256 lpZappedIn, , ) = ZapIn(0, false);

        onDeposit(msg.sender, lpZappedIn);
    }

    /**
     * @notice Withdraw all staked LP tokens + rewards from farm. Only possilbe after harvest interval.
      Use emergency withdraw if you want to withdraw before harvest interval. No rewards will be returned.
     * @dev Farmer's can choose to get back LP tokens or Zap out to get Koromaru and Eth
     */
    function withdraw(bool _useZapOut) external whenNotPaused nonReentrant {
        uint256 balance = userInfo[msg.sender].amount;
        require(balance > 0, "Withdraw: You have no balance");
        updateFarm();

        if (_useZapOut) {
            zapLPOut(balance);
        } else {
            koromaruUniV2.transfer(msg.sender, balance);
        }

        onWithdraw(msg.sender);
        emit Withdraw(msg.sender, balance);
    }

    /**
     * @notice Harvest all rewards from farm
     */
    function harvest() external whenNotPaused nonReentrant {
        updateFarm();
        harvestRewards(msg.sender);
    }

    /**
     * @notice Compounds rewards from farm. Only available after harvest interval is reached for farmer.
     */
    function compound() external whenNotPaused nonReentrant {
        updateFarm();
        UserInfo storage user = userInfo[msg.sender];
        require(
            block.timestamp - user.lastRewardHarvestedTime >=
                rewardHarvestingInterval,
            "HarvestRewards: Not yet ripe"
        );

        uint256 koroCompounded;
        uint256 ethCompounded;

        uint256 pendinKoroTokens = user
            .amount
            .mul(farmInfo.accKoroRewardsPerShare)
            .div(precisionScaleUp)
            .sub(user.koroDebt)
            .add(user.unpaidKoro);

        uint256 pendingEthWei = user
            .amount
            .mul(farmInfo.accEthRewardsPerShare)
            .div(precisionScaleUp)
            .sub(user.ethDebt)
            .add(user.unpaidEth);
        {
            uint256 koromaruBalance = koromaru.balanceOf(address(this));
            if (pendinKoroTokens > 0) {
                if (pendinKoroTokens > koromaruBalance) {
                    // not enough koro balance to reward farmer
                    user.unpaidKoro = pendinKoroTokens.sub(koromaruBalance);
                    totalKoroRewarded = totalKoroRewarded.add(koromaruBalance);
                    koroCompounded = koromaruBalance;
                } else {
                    user.unpaidKoro = 0;
                    totalKoroRewarded = totalKoroRewarded.add(pendinKoroTokens);
                    koroCompounded = pendinKoroTokens;
                }
            }
        }

        {
            uint256 ethBalance = getEthBalance();
            if (pendingEthWei > ethBalance) {
                // not enough Eth balance to reward farmer
                user.unpaidEth = pendingEthWei.sub(ethBalance);
                totalEthRewarded = totalEthRewarded.add(ethBalance);
                IWETH(WETHAddress).deposit{value: ethBalance}();
                ethCompounded = ethBalance;
            } else {
                user.unpaidEth = 0;
                totalEthRewarded = totalEthRewarded.add(pendingEthWei);
                IWETH(WETHAddress).deposit{value: pendingEthWei}();
                ethCompounded = pendingEthWei;
            }
        }
        (uint256 LP, , ) = _zapInMulti(koroCompounded, ethCompounded);

        onCompound(msg.sender, LP);
        emit Compound(msg.sender, koroCompounded, ethCompounded);
    }

    /**
     * @notice Returns time in seconds to next harvest.
     */
    function timeToHarvest(address _user)
        public
        view
        whenNotPaused
        returns (uint256)
    {
        UserInfo storage user = userInfo[_user];
        if (
            block.timestamp - user.lastRewardHarvestedTime >=
            rewardHarvestingInterval
        ) {
            return 0;
        }
        return
            user.lastRewardHarvestedTime.sub(
                block.timestamp.sub(rewardHarvestingInterval)
            );
    }

    /**
     * @notice Withdraw all staked LP tokens without rewards.
     */
    function emergencyWithdraw() external nonReentrant {
        UserInfo storage user = userInfo[msg.sender];
        koromaruUniV2.safeTransfer(address(msg.sender), user.amount);
        emit EmergencyWithdraw(msg.sender, user.amount);

        userInfo[msg.sender] = UserInfo(0, 0, 0, 0, 0, 0);
    }

    //--------------- End Contract Farmer  -------------------

    //---------------- Contract Utils  ----------------------

    /**
     * @notice Calculates the total amount of rewards per day in USD
     * @dev The returned value is in USD * 1e18 (WETH decimals), actual USD value is calculated by dividing the value by 1e18
     */
    function getUSDDailyRewards() public view whenNotPaused returns (uint256) {
        uint256 stakedLP = koromaruUniV2.balanceOf(address(this));
        uint256 totalLPsupply = koromaruUniV2.totalSupply();
        uint256 stakedTVL = stakedLP.mul(getTVLUsingKoro()).div(totalLPsupply);
        return APR.mul(stakedTVL).div(_1hundred_Percent);
    }

    /**
     * @notice Calculates the total amount of rewards per second in USD
     * @dev The returned value is in USD * 1e18 (WETH decimals), actual USD value is calculated by dividing the value by 1e18
     */
    function getUSDRewardsPerSecond() internal view returns (uint256) {
        // final return value should be divided by (1e18) (i.e WETH decimals) to get USD value
        uint256 dailyRewards = getUSDDailyRewards();
        return dailyRewards.div(secsPerDay);
    }

    /**
     * @notice Calculates the total number of koromaru token rewards per second
     * @dev The returned value must be divided by the koromaru token decimals to get the actual value
     */
    function getNumberOfKoroRewardsPerSecond(uint256 _koroRewardAllocation)
        internal
        view
        returns (uint256)
    {
        uint256 priceOfUintKoro = getLatestKoroPrice(); // 1e18
        uint256 rewardsPerSecond = getUSDRewardsPerSecond(); // 1e18

        return
            rewardsPerSecond
                .mul(_koroRewardAllocation)
                .mul(koromaruDecimals)
                .div(priceOfUintKoro)
                .div(_1hundred_Percent); //to be div by koro decimals (i.e 1**(18-18+korodecimals)
    }

    /**
     * @notice Calculates the total amount of Eth rewards per second
     * @dev The returned value must be divided by the 1e18 to get the actual value
     */
    function getAmountOfEthRewardsPerSecond(uint256 _ethRewardAllocation)
        internal
        view
        returns (uint256)
    {
        uint256 priceOfUintEth = getLatestEthPrice(); // 1e8
        uint256 rewardsPerSecond = getUSDRewardsPerSecond(); // 1e18
        uint256 scaleUpToWei = 1e8;

        return
            rewardsPerSecond
                .mul(_ethRewardAllocation)
                .mul(scaleUpToWei)
                .div(priceOfUintEth)
                .div(_1hundred_Percent); // to be div by 1e18 (i.e 1**(18-8+8)
    }

    /**
     * @notice Returns the rewards rate/second for both koromaru and eth
     */
    function getRewardsPerSecond()
        public
        view
        whenNotPaused
        returns (uint256 koroRewards, uint256 ethRewards)
    {
        require(
            koroRewardAllocation.add(ethRewardAllocation) == _1hundred_Percent,
            "getRewardsPerSecond: Invalid reward allocation ratio"
        );

        koroRewards = getNumberOfKoroRewardsPerSecond(koroRewardAllocation);
        ethRewards = getAmountOfEthRewardsPerSecond(ethRewardAllocation);
    }

    /**
     * @notice Calculates and returns the TVL in USD (actaul TVL, not staked TVL)
     * @dev Uses Eth price from price feed to calculate the TVL in USD
     */
    function getTVL() public view returns (uint256 tvl) {
        // final return value should be divided by (1e18) (i.e WETH decimals) to get USD value
        IUniswapV2Pair koroPair = IUniswapV2Pair(address(koromaruUniV2));
        address token0 = koroPair.token0();
        (uint256 resv0, uint256 resv1, ) = koroPair.getReserves();
        uint256 TVLEth = 2 *
            (address(token0) == address(koromaru) ? resv1 : resv0);
        uint256 priceOfEth = getLatestEthPrice();

        tvl = TVLEth.mul(priceOfEth).div(EthPriceFeedDecimal);
    }

    /**
     * @notice Calculates and returns the TVL in USD (actaul TVL, not staked TVL)
     * @dev Uses minimum Eth price in USD for 1 koromaru token to calculate the TVL in USD
     */
    function getTVLUsingKoro() public view whenNotPaused returns (uint256 tvl) {
        // returned value should be divided by (1e18) (i.e WETH decimals) to get USD value
        IUniswapV2Pair koroPair = IUniswapV2Pair(address(koromaruUniV2));
        address token0 = koroPair.token0();
        (uint256 resv0, uint256 resv1, ) = koroPair.getReserves();
        uint256 TVLKoro = 2 *
            (address(token0) == address(koromaru) ? resv0 : resv1);
        uint256 priceOfKoro = getLatestKoroPrice();

        tvl = TVLKoro.mul(priceOfKoro).div(koromaruDecimals);
    }

    /**
     * @notice Get's the latest Eth price in USD
     * @dev Uses ChainLink price feed to get the latest Eth price in USD
     */
    function getLatestEthPrice() internal view returns (uint256) {
        // final return value should be divided by 1e8 to get USD value
        (, int256 price, , , ) = priceFeed.latestRoundData();
        return uint256(price);
    }

    /**
     * @notice Get's the latest Unit Koro price in USD
     * @dev Uses estimated price per koromaru token in USD
     */
    function getLatestKoroPrice() internal view returns (uint256) {
        // returned value must be divided by 1e18 (i.e WETH decimals) to get USD value
        IUniswapV2Pair koroPair = IUniswapV2Pair(address(koromaruUniV2));
        address token0 = koroPair.token0();
        bool isKoro = address(token0) == address(koromaru);

        (uint256 resv0, uint256 resv1, ) = koroPair.getReserves();
        uint256 oneKoro = 1 * koromaruDecimals;

        uint256 optimalWethAmount = uniswapRouter.getAmountOut(
            oneKoro,
            isKoro ? resv0 : resv1,
            isKoro ? resv1 : resv0
        ); //uniswapRouter.quote(oneKoro, isKoro ? resv1 : resv0, isKoro ? resv0 : resv1);
        uint256 priceOfEth = getLatestEthPrice();

        return optimalWethAmount.mul(priceOfEth).div(EthPriceFeedDecimal);
    }

    function onDeposit(address _user, uint256 _amount) internal {
        require(!reachedMaxLimit(), "KOROFARM: Farm is full");
        UserInfo storage user = userInfo[_user];
        updateFarm();

        if (user.amount > 0) {
            // record as unpaid
            user.unpaidKoro = user
                .amount
                .mul(farmInfo.accKoroRewardsPerShare)
                .div(precisionScaleUp)
                .sub(user.koroDebt)
                .add(user.unpaidKoro);

            user.unpaidEth = user
                .amount
                .mul(farmInfo.accEthRewardsPerShare)
                .div(precisionScaleUp)
                .sub(user.ethDebt)
                .add(user.unpaidEth);
        }

        user.amount = user.amount.add(_amount);
        user.koroDebt = user.amount.mul(farmInfo.accKoroRewardsPerShare).div(
            precisionScaleUp
        );
        user.ethDebt = user.amount.mul(farmInfo.accEthRewardsPerShare).div(
            precisionScaleUp
        );

        if (
            (block.timestamp - user.lastRewardHarvestedTime >=
                rewardHarvestingInterval) || (rewardHarvestingInterval == 0)
        ) {
            user.lastRewardHarvestedTime = block.timestamp;
        }

        emit Deposit(_user, _amount);
    }

    function onWithdraw(address _user) internal {
        harvestRewards(_user);
        userInfo[msg.sender].amount = 0;

        userInfo[msg.sender].koroDebt = 0;
        userInfo[msg.sender].ethDebt = 0;
    }

    function onCompound(address _user, uint256 _amount) internal {
        require(!reachedMaxLimit(), "KOROFARM: Farm is full");
        UserInfo storage user = userInfo[_user];

        user.amount = user.amount.add(_amount);
        user.koroDebt = user.amount.mul(farmInfo.accKoroRewardsPerShare).div(
            precisionScaleUp
        );
        user.ethDebt = user.amount.mul(farmInfo.accEthRewardsPerShare).div(
            precisionScaleUp
        );

        user.lastRewardHarvestedTime = block.timestamp;
    }

    function harvestRewards(address _user) internal {
        UserInfo storage user = userInfo[_user];
        require(
            block.timestamp - user.lastRewardHarvestedTime >=
                rewardHarvestingInterval,
            "HarvestRewards: Not yet ripe"
        );

        uint256 pendinKoroTokens = user
            .amount
            .mul(farmInfo.accKoroRewardsPerShare)
            .div(precisionScaleUp)
            .sub(user.koroDebt)
            .add(user.unpaidKoro);

        uint256 pendingEthWei = user
            .amount
            .mul(farmInfo.accEthRewardsPerShare)
            .div(precisionScaleUp)
            .sub(user.ethDebt)
            .add(user.unpaidEth);

        {
            uint256 koromaruBalance = koromaru.balanceOf(address(this));
            if (pendinKoroTokens > 0) {
                if (pendinKoroTokens > koromaruBalance) {
                    // not enough koro balance to reward farmer
                    koromaru.safeTransfer(_user, koromaruBalance);
                    user.unpaidKoro = pendinKoroTokens.sub(koromaruBalance);
                    totalKoroRewarded = totalKoroRewarded.add(koromaruBalance);
                    emit KoroRewardsHarvested(_user, koromaruBalance);
                } else {
                    koromaru.safeTransfer(_user, pendinKoroTokens);
                    user.unpaidKoro = 0;
                    totalKoroRewarded = totalKoroRewarded.add(pendinKoroTokens);
                    emit KoroRewardsHarvested(_user, pendinKoroTokens);
                }
            }
        }
        {
            uint256 ethBalance = getEthBalance();
            if (pendingEthWei > ethBalance) {
                // not enough Eth balance to reward farmer
                (bool sent, ) = _user.call{value: ethBalance}("");
                require(sent, "Failed to send Ether");
                user.unpaidEth = pendingEthWei.sub(ethBalance);
                totalEthRewarded = totalEthRewarded.add(ethBalance);
                emit EthRewardsHarvested(_user, ethBalance);
            } else {
                (bool sent, ) = _user.call{value: pendingEthWei}("");
                require(sent, "Failed to send Ether");
                user.unpaidEth = 0;
                totalEthRewarded = totalEthRewarded.add(pendingEthWei);
                emit EthRewardsHarvested(_user, pendingEthWei);
            }
        }
        user.koroDebt = user.amount.mul(farmInfo.accKoroRewardsPerShare).div(
            precisionScaleUp
        );
        user.ethDebt = user.amount.mul(farmInfo.accEthRewardsPerShare).div(
            precisionScaleUp
        );
        user.lastRewardHarvestedTime = block.timestamp;
    }

    /**
     * @notice Convert's Koro LP tokens back to Koro and Eth
     */
    function zapLPOut(uint256 _amount)
        private
        returns (uint256 _koroTokens, uint256 _ether)
    {
        (_koroTokens, _ether) = zapOut(_amount);
        (bool sent, ) = msg.sender.call{value: _ether}("");
        require(sent, "Failed to send Ether");
        koromaru.safeTransfer(msg.sender, _koroTokens);
    }

    function getEthBalance() public view returns (uint256) {
        return address(this).balance;
    }

    function getUserInfo(address _user)
        public
        view
        returns (
            uint256 amount,
            uint256 stakedInUsd,
            uint256 timeToHarves,
            uint256 pendingKoro,
            uint256 pendingEth
        )
    {
        amount = userInfo[_user].amount;
        timeToHarves = timeToHarvest(_user);
        (pendingKoro, pendingEth) = getPendingRewards(_user);

        uint256 stakedLP = koromaruUniV2.balanceOf(address(this));
        stakedInUsd = stakedLP > 0
            ? userInfo[_user].amount.mul(getStakedTVL()).div(stakedLP)
            : 0;
    }

    function getFarmInfo()
        public
        view
        returns (
            uint256 tvl,
            uint256 totalStaked,
            uint256 circSupply,
            uint256 dailyROI,
            uint256 ethDistribution,
            uint256 koroDistribution
        )
    {
        tvl = getStakedTVL();
        totalStaked = koromaruUniV2.balanceOf(address(this));
        circSupply = getCirculatingSupplyLocked();
        dailyROI = APR;
        ethDistribution = ethRewardAllocation;
        koroDistribution = koroRewardAllocation;
    }

    function getCirculatingSupplyLocked() public view returns (uint256) {
        address deadWallet = address(
            0x000000000000000000000000000000000000dEaD
        );
        IUniswapV2Pair koroPair = IUniswapV2Pair(address(koromaruUniV2));
        address token0 = koroPair.token0();
        (uint256 resv0, uint256 resv1, ) = koroPair.getReserves();
        uint256 koroResv = address(token0) == address(koromaru) ? resv0 : resv1;
        uint256 lpSupply = koromaruUniV2.totalSupply();
        uint256 koroCirculatingSupply = koromaru.totalSupply().sub(
            koromaru.balanceOf(deadWallet)
        );
        uint256 stakedLp = koromaruUniV2.balanceOf(address(this));

        return
            (stakedLp.mul(koroResv).mul(1e18).div(lpSupply)).div(
                koroCirculatingSupply
            ); // divide by 1e18
    }

    function approveRouterIfNotApproved() private {
        if (koromaru.allowance(address(this), address(uniswapRouter)) == 0) {
            koromaru.safeApprove(address(uniswapRouter), type(uint256).max);
        }

        if (
            koromaruUniV2.allowance(address(this), address(uniswapRouter)) == 0
        ) {
            koromaruUniV2.approve(address(uniswapRouter), type(uint256).max);
        }
    }

    function reachedMaxLimit() public view returns (bool) {
        uint256 lockedLP = koromaruUniV2.balanceOf(address(this));
        if (maxLPLimit < 1) return false; // unlimited

        if (lockedLP >= maxLPLimit) return true;

        return false;
    }

    //--------------- End Contract Utils  -------------------

    receive() external payable {
        emit IncreaseEthRewardPool(msg.value);
    }
}

File 2 of 11 : AggregatorV3Interface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface AggregatorV3Interface {
  function decimals() external view returns (uint8);

  function description() external view returns (string memory);

  function version() external view returns (uint256);

  // getRoundData and latestRoundData should both raise "No data present"
  // if they do not have data to report, instead of returning unset values
  // which could be misinterpreted as actual reported values.
  function getRoundData(uint80 _roundId)
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
}

File 3 of 11 : EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/structs/EnumerableSet.sol)

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastvalue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastvalue;
                // Update the index for the moved value
                set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        return _values(set._inner);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        assembly {
            result := store
        }

        return result;
    }
}

File 4 of 11 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 5 of 11 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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 `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, 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 `sender` to `recipient` 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 sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

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

File 6 of 11 : SafeMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 7 of 11 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

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

File 8 of 11 : Pausable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (security/Pausable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

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

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

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

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

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

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

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

File 9 of 11 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * 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 Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing 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 10 of 11 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Address.sol)

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

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

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

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

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

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

File 11 of 11 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (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;
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_koromaru","type":"address"},{"internalType":"address","name":"_koromaruUniV2","type":"address"},{"internalType":"address","name":"_UniSwapV2FactoryAddress","type":"address"},{"internalType":"address","name":"_uniswapRouter","type":"address"},{"internalType":"uint256","name":"_apr","type":"uint256"},{"internalType":"uint256","name":"_taxToRefund","type":"uint256"},{"internalType":"uint256","name":"_koromaruTokenDecimals","type":"uint256"},{"internalType":"uint256","name":"_koroRewardAllocation","type":"uint256"},{"internalType":"uint256","name":"_rewardHarvestingInterval","type":"uint256"},{"internalType":"uint256","name":"_zapKoroLimit","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"OldAPR","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"NewAPR","type":"uint256"}],"name":"APRUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"koro","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"eth","type":"uint256"}],"name":"Compound","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"Ethrewards","type":"uint256"}],"name":"EthRewardsHarvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"IncreaseEthRewardPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"IncreaseKoroRewardPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"Kororewards","type":"uint256"}],"name":"KoroRewardsHarvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ZappedIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"koroAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"Eth","type":"uint256"}],"name":"ZappedOut","type":"event"},{"inputs":[],"name":"APR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UniSwapV2FactoryAddress","outputs":[{"internalType":"contract IUniswapV2Factory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETHAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"compound","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositEthOnly","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"depositEthRewards","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositKoroLPTokensOnly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositKoroRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositKoroTokensOnly","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_koro","type":"uint256"},{"internalType":"uint256","name":"_koroLp","type":"uint256"}],"name":"depositMultipleAssets","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ethRewardAllocation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"farmInfo","outputs":[{"internalType":"uint256","name":"accKoroRewardsPerShare","type":"uint256"},{"internalType":"uint256","name":"accEthRewardsPerShare","type":"uint256"},{"internalType":"uint256","name":"lastRewardTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCirculatingSupplyLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEthBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFarmInfo","outputs":[{"internalType":"uint256","name":"tvl","type":"uint256"},{"internalType":"uint256","name":"totalStaked","type":"uint256"},{"internalType":"uint256","name":"circSupply","type":"uint256"},{"internalType":"uint256","name":"dailyROI","type":"uint256"},{"internalType":"uint256","name":"ethDistribution","type":"uint256"},{"internalType":"uint256","name":"koroDistribution","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_farmer","type":"address"}],"name":"getPendingRewards","outputs":[{"internalType":"uint256","name":"pendinKoroTokens","type":"uint256"},{"internalType":"uint256","name":"pendingEthWei","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardsPerSecond","outputs":[{"internalType":"uint256","name":"koroRewards","type":"uint256"},{"internalType":"uint256","name":"ethRewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakedTVL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTVL","outputs":[{"internalType":"uint256","name":"tvl","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTVLUsingKoro","outputs":[{"internalType":"uint256","name":"tvl","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUSDDailyRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getUserInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"stakedInUsd","type":"uint256"},{"internalType":"uint256","name":"timeToHarves","type":"uint256"},{"internalType":"uint256","name":"pendingKoro","type":"uint256"},{"internalType":"uint256","name":"pendingEth","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"koroRewardAllocation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"koromaru","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"koromaruUniV2","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseAndRemoveRewardPools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reachedMaxLimit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resetPriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_dailyAPR","type":"uint256"}],"name":"setDailyAPR","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxLPLimit","type":"uint256"}],"name":"setMaxLPLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_koroAllocation","type":"uint256"}],"name":"setRewardAllocations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_taxToRefund","type":"uint256"}],"name":"setTaxRefundPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_limit","type":"uint256"}],"name":"setZapLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"timeToHarvest","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalEthRewarded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalKoroRewarded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapRouter","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateFarm","outputs":[{"components":[{"internalType":"uint256","name":"accKoroRewardsPerShare","type":"uint256"},{"internalType":"uint256","name":"accEthRewardsPerShare","type":"uint256"},{"internalType":"uint256","name":"lastRewardTimestamp","type":"uint256"}],"internalType":"struct KoroFarms.FarmInfo","name":"farm","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_usdt_eth_aggregator","type":"address"}],"name":"updatePriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"koroDebt","type":"uint256"},{"internalType":"uint256","name":"ethDebt","type":"uint256"},{"internalType":"uint256","name":"unpaidKoro","type":"uint256"},{"internalType":"uint256","name":"unpaidEth","type":"uint256"},{"internalType":"uint256","name":"lastRewardHarvestedTime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_useZapOut","type":"bool"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"withdrawForeignToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6101206040523480156200001257600080fd5b50604051620066c3380380620066c38339810160408190526200003591620008ee565b898989896200004433620002b8565b6000805460ff60a01b19169055600180556001600160601b0319606085811b821660805284811b821660a05283901b1660c052600280546001600160a01b0383166001600160a01b03199091168117909155604080516315ab88c960e31b8152905163ad5c464891600480820192602092909190829003018186803b158015620000cd57600080fd5b505afa158015620000e2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000108919062000987565b60601b6001600160601b03191660e05250505061271084111590506200018e5760405162461bcd60e51b815260206004820152603060248201527f736574526577617264416c6c6f636174696f6e733a20496e76616c696420726560448201526f3bb0b932399030b63637b1b0ba34b7b760811b60648201526084015b60405180910390fd5b612710861115620001e25760405162461bcd60e51b815260206004820152601e60248201527f5365744461696c794150523a20496e76616c6964204150522056616c75650000604482015260640162000185565b620001ec62000308565b620001f984600a62000ab8565b610100526200020a84600a62000ab8565b62000216908262000ac6565b600a55600586905560078390556200023d61271084620004f1602090811b620031a217901c565b6008556004859055604080516060810182526000808252602082018190524291909201819052600b829055600c91909155600d556200027e82600162000ac6565b6006555050600380546001600160a01b031916735f4ec3df9cbd43714fe2740f5e3616155c5b84191790555062000bc69650505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b608051600254604051636eb1769f60e11b81523060048201526001600160a01b03909116602482015260609190911c9063dd62ed3e9060440160206040518083038186803b1580156200035a57600080fd5b505afa1580156200036f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000395919062000ae8565b620003ca57600254608051620003ca9160609190911c906001600160a01b031660001962000508602090811b620031b517901c565b60a051600254604051636eb1769f60e11b81523060048201526001600160a01b03909116602482015260609190911c9063dd62ed3e9060440160206040518083038186803b1580156200041c57600080fd5b505afa15801562000431573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000457919062000ae8565b620004ef5760a05160025460405163095ea7b360e01b81526001600160a01b039091166004820152600019602482015260609190911c9063095ea7b390604401602060405180830381600087803b158015620004b257600080fd5b505af1158015620004c7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004ed919062000b02565b505b565b6000620004ff828462000b26565b90505b92915050565b801580620005965750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b1580156200055957600080fd5b505afa1580156200056e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000594919062000ae8565b155b6200060a5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e636500000000000000000000606482015260840162000185565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b17909152620006629185916200066716565b505050565b6000620006c3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166200074560201b6200330c179092919060201c565b805190915015620006625780806020019051810190620006e4919062000b02565b620006625760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000185565b606062000756848460008562000760565b90505b9392505050565b606082471015620007c35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000185565b843b620008135760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000185565b600080866001600160a01b0316858760405162000831919062000b73565b60006040518083038185875af1925050503d806000811462000870576040519150601f19603f3d011682016040523d82523d6000602084013e62000875565b606091505b5090925090506200088882828662000893565b979650505050505050565b60608315620008a457508162000759565b825115620008b55782518084602001fd5b8160405162461bcd60e51b815260040162000185919062000b91565b80516001600160a01b0381168114620008e957600080fd5b919050565b6000806000806000806000806000806101408b8d0312156200090f57600080fd5b6200091a8b620008d1565b99506200092a60208c01620008d1565b98506200093a60408c01620008d1565b97506200094a60608c01620008d1565b965060808b0151955060a08b0151945060c08b0151935060e08b015192506101008b015191506101208b015190509295989b9194979a5092959850565b6000602082840312156200099a57600080fd5b620004ff82620008d1565b634e487b7160e01b600052601160045260246000fd5b600181815b80851115620009fc578160001904821115620009e057620009e0620009a5565b80851615620009ee57918102915b93841c9390800290620009c0565b509250929050565b60008262000a155750600162000502565b8162000a245750600062000502565b816001811462000a3d576002811462000a485762000a68565b600191505062000502565b60ff84111562000a5c5762000a5c620009a5565b50506001821b62000502565b5060208310610133831016604e8410600b841016171562000a8d575081810a62000502565b62000a998383620009bb565b806000190482111562000ab05762000ab0620009a5565b029392505050565b6000620004ff838362000a04565b600081600019048311821515161562000ae35762000ae3620009a5565b500290565b60006020828403121562000afb57600080fd5b5051919050565b60006020828403121562000b1557600080fd5b815180151581146200075957600080fd5b60008282101562000b3b5762000b3b620009a5565b500390565b60005b8381101562000b5d57818101518382015260200162000b43565b8381111562000b6d576000848401525b50505050565b6000825162000b8781846020870162000b40565b9190910192915050565b602081526000825180602084015262000bb281604085016020870162000b40565b601f01601f19169190910160400192915050565b60805160601c60a05160601c60c05160601c60e05160601c6101005161593262000d9160003960008181610ed501528181611848015281816137640152613e780152600081816103b2015281816129ad01528181612a4d01528181612e1101528181612ea7015281816144220152614884015260008181610883015261507401526000818161080f01528181610a2a01528181610b0001528181610b8801528181610c7f01528181610d5301528181610f2b01528181610fab01528181611065015281816111cf015281816113bd015281816119cf01528181611dfd015281816120a301528181612254015281816123e6015281816126bb0152818161317001528181613609015281816146a901528181614753015281816147e60152614d300152600081816106ed01528181610e780152818161118a0152818161128701528181611305015281816115040152818161159d0152818161191f01528181611d61015281816121c801528181612d15015281816136a301528181613a4b01528181613ae201528181613b780152818161405d0152818161450101528181614557015281816146010152818161483401528181614927015281816149c30152614ad201526159326000f3fe6080604052600436106102cd5760003560e01c80637d97a04311610175578063bd30558e116100dc578063e88c681411610095578063f54ca63c1161006f578063f54ca63c146108e5578063f69e20461461091c578063f6ed201714610931578063fa1e1cd71461095157600080fd5b8063e88c681414610871578063eaa0daa9146108a5578063f2fde38b146108c557600080fd5b8063bd30558e146107df578063bdd8e782146107f5578063be5dc462146107fd578063db2e21bc14610831578063df439d0814610846578063e1e4c77d1461085b57600080fd5b806395877f781161012e57806395877f781461074d57806397b3fcaa1461076d5780639d37db4314610782578063a810a54c14610797578063ae38b386146107b7578063b3ac27bf146107d757600080fd5b80637d97a043146106865780638456cb59146106a6578063885a4cd0146106bb57806389c6e7c3146106db5780638da5cb5b1461070f578063956101791461072d57600080fd5b8063360feb80116102345780635ef837bc116101ed57806370ed0ada116101c757806370ed0ada14610614578063715018a614610627578063735de9f71461063c57806376f259b21461065c57600080fd5b80635ef837bc146105965780636102d69b146105b65780636386c1c7146105cc57600080fd5b8063360feb80146104eb5780633f4ba83a1461050157806342f8d36f146105165780634641257d1461053657806354b36f591461054b5780635c975abb1461056b57600080fd5b806310a62bd31161028657806310a62bd314610401578063169dd71d146104165780631959a002146104365780631d49d66c146104865780632d678dae146104c057806333ddd65e146104d557600080fd5b8063072453101461030c5780630747091d1461032157806309434f28146103495780630ae2bac61461038b5780630af88b24146103a05780630f21dc86146103ec57600080fd5b36610307576040513481527f0f2115e51903c319ad6853769c5626af4d72fb85522e0888331f77d618558ef89060200160405180910390a1005b600080fd5b61031f61031a36600461547b565b610971565b005b34801561032d57600080fd5b50610336610abd565b6040519081526020015b60405180910390f35b34801561035557600080fd5b5061035e610c56565b604080519687526020870195909552938501929092526060840152608083015260a082015260c001610340565b34801561039757600080fd5b50610336610d24565b3480156103ac57600080fd5b506103d47f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610340565b3480156103f857600080fd5b50610336610f09565b34801561040d57600080fd5b50610336611059565b34801561042257600080fd5b5061031f61043136600461549d565b611469565b34801561044257600080fd5b5061035e6104513660046154cb565b600e60205260009081526040902080546001820154600283015460038401546004850154600590950154939492939192909186565b34801561049257600080fd5b50600b54600c54600d546104a592919083565b60408051938452602084019290925290820152606001610340565b3480156104cc57600080fd5b5061031f611498565b3480156104e157600080fd5b50610336600f5481565b3480156104f757600080fd5b5061033660075481565b34801561050d57600080fd5b5061031f611638565b34801561052257600080fd5b5061031f61053136600461549d565b6116e5565b34801561054257600080fd5b5061031f6117af565b34801561055757600080fd5b5061031f61056636600461549d565b611819565b34801561057757600080fd5b50600054600160a01b900460ff165b6040519015158152602001610340565b3480156105a257600080fd5b5061031f6105b136600461549d565b611873565b3480156105c257600080fd5b5061033660085481565b3480156105d857600080fd5b506105ec6105e73660046154cb565b611981565b604080519586526020860194909452928401919091526060830152608082015260a001610340565b34801561062057600080fd5b5047610336565b34801561063357600080fd5b5061031f611a9c565b34801561064857600080fd5b506002546103d4906001600160a01b031681565b34801561066857600080fd5b50610671611ad2565b60408051928352602083019190915201610340565b34801561069257600080fd5b506103366106a13660046154cb565b611ba1565b3480156106b257600080fd5b5061031f611c30565b3480156106c757600080fd5b5061031f6106d63660046154cb565b611cb7565b3480156106e757600080fd5b506103d47f000000000000000000000000000000000000000000000000000000000000000081565b34801561071b57600080fd5b506000546001600160a01b03166103d4565b34801561073957600080fd5b5061031f61074836600461549d565b611f33565b34801561075957600080fd5b5061031f6107683660046154cb565b612052565b34801561077957600080fd5b5061033661209e565b34801561078e57600080fd5b50610586612232565b3480156107a357600080fd5b5061031f6107b23660046154f6565b6122fc565b3480156107c357600080fd5b5061031f6107d236600461549d565b6124b2565b61031f6124e1565b3480156107eb57600080fd5b5061033660055481565b61031f6125b9565b34801561080957600080fd5b506103d47f000000000000000000000000000000000000000000000000000000000000000081565b34801561083d57600080fd5b5061031f61267a565b34801561085257600080fd5b5061031f612790565b34801561086757600080fd5b5061033660105481565b34801561087d57600080fd5b506103d47f000000000000000000000000000000000000000000000000000000000000000081565b3480156108b157600080fd5b5061031f6108c036600461549d565b6127e2565b3480156108d157600080fd5b5061031f6108e03660046154cb565b61288e565b3480156108f157600080fd5b506108fa612929565b6040805182518152602080840151908201529181015190820152606001610340565b34801561092857600080fd5b5061031f612ba1565b34801561093d57600080fd5b5061067161094c3660046154cb565b612f7f565b34801561095d57600080fd5b5061031f61096c36600461549d565b6130c4565b600054600160a01b900460ff16156109a45760405162461bcd60e51b815260040161099b90615513565b60405180910390fd5b600260015414156109c75760405162461bcd60e51b815260040161099b9061553d565b6002600155600a548211156109ee5760405162461bcd60e51b815260040161099b90615574565b6000803411610a0757610a02836000613323565b610a12565b610a12836001613323565b50909150508115610a5257610a526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330856133f1565b6000610a5e83836155d5565b9050610a81612710610a7b6004548761342f90919063ffffffff16565b9061343b565b336000908152600e602052604081206003018054909190610aa39084906155d5565b90915550610ab390503382613447565b5050600180555050565b60008054600160a01b900460ff1615610ae85760405162461bcd60e51b815260040161099b90615513565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b158015610b4a57600080fd5b505afa158015610b5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8291906155ed565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610bdf57600080fd5b505afa158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906155ed565b90506000610c3182610a7b610c2a610d24565b869061342f565b9050610c4e612710610a7b8360055461342f90919063ffffffff16565b935050505090565b600080600080600080610c67610f09565b6040516370a0823160e01b81523060048201529096507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b158015610cc957600080fd5b505afa158015610cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0191906155ed565b9450610d0b611059565b9350600554925060085491506007549050909192939495565b60008054600160a01b900460ff1615610d4f5760405162461bcd60e51b815260040161099b90615513565b60007f000000000000000000000000000000000000000000000000000000000000000090506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610daf57600080fd5b505afa158015610dc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de79190615606565b9050600080836001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015610e2557600080fd5b505afa158015610e39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5d919061563a565b506001600160701b031691506001600160701b0316915060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614610eb55781610eb7565b825b610ec290600261568a565b90506000610ece613604565b9050610efe7f0000000000000000000000000000000000000000000000000000000000000000610a7b848461342f565b965050505050505090565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b158015610f6d57600080fd5b505afa158015610f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa591906155ed565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561100257600080fd5b505afa158015611016573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103a91906155ed565b905061105281610a7b61104b610d24565b859061342f565b9250505090565b60008061dead905060007f000000000000000000000000000000000000000000000000000000000000000090506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156110c157600080fd5b505afa1580156110d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f99190615606565b9050600080836001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561113757600080fd5b505afa15801561114b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116f919061563a565b506001600160701b031691506001600160701b0316915060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316146111c757816111c9565b825b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561122657600080fd5b505afa15801561123a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125e91906155ed565b6040516370a0823160e01b81526001600160a01b03898116600483015291925060009161139a917f0000000000000000000000000000000000000000000000000000000000000000909116906370a082319060240160206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130391906155ed565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561135c57600080fd5b505afa158015611370573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139491906155ed565b906131a2565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b1580156113ff57600080fd5b505afa158015611413573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143791906155ed565b905061145b82610a7b8581670de0b6b3a7640000611455878b61342f565b9061342f565b995050505050505050505090565b6000546001600160a01b031633146114935760405162461bcd60e51b815260040161099b906156a9565b600455565b6000546001600160a01b031633146114c25760405162461bcd60e51b815260040161099b906156a9565b600054600160a01b900460ff16156114ec5760405162461bcd60e51b815260040161099b90615513565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561154e57600080fd5b505afa158015611562573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158691906155ed565b9050303181156115c4576115c46001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163384613865565b801561163457604051600090339083908381818185875af1925050503d806000811461160c576040519150601f19603f3d011682016040523d82523d6000602084013e611611565b606091505b50509050806116325760405162461bcd60e51b815260040161099b906156de565b505b5050565b6000546001600160a01b031633146116625760405162461bcd60e51b815260040161099b906156a9565b600054600160a01b900460ff166116b25760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161099b565b6116ba613895565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b6000546001600160a01b0316331461170f5760405162461bcd60e51b815260040161099b906156a9565b611717612929565b5061271081111561176a5760405162461bcd60e51b815260206004820152601e60248201527f5365744461696c794150523a20496e76616c6964204150522056616c75650000604482015260640161099b565b600580549082905560408051828152602081018490527fd2d659d197cf77652feb866d2a49b71684b0e7b0d92bde0b26163f77e2e25a2d910160405180910390a15050565b600054600160a01b900460ff16156117d95760405162461bcd60e51b815260040161099b90615513565b600260015414156117fc5760405162461bcd60e51b815260040161099b9061553d565b6002600155611809612929565b5061181333613932565b60018055565b6000546001600160a01b031633146118435760405162461bcd60e51b815260040161099b906156a9565b61186d7f00000000000000000000000000000000000000000000000000000000000000008261568a565b600a5550565b6000546001600160a01b0316331461189d5760405162461bcd60e51b815260040161099b906156a9565b600260015414156118c05760405162461bcd60e51b815260040161099b9061553d565b6002600155806119125760405162461bcd60e51b815260206004820152601d60248201527f4b4f524f4641524d3a20496e76616c6964204b6f726f20416d6f756e74000000604482015260640161099b565b6119476001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330846133f1565b6040518181527fbcb2ea58f5b99aef9322cfc4dc10e836fa7b8bb0d698199d1cb6207f9264eb569060200160405180910390a15060018055565b6001600160a01b0381166000908152600e6020526040812054908080806119a786611ba1565b92506119b286612f7f565b6040516370a0823160e01b815230600482015291935091506000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b158015611a1957600080fd5b505afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5191906155ed565b905060008111611a62576000611a90565b611a9081610a7b611a71610f09565b6001600160a01b038b166000908152600e60205260409020549061342f565b94505091939590929450565b6000546001600160a01b03163314611ac65760405162461bcd60e51b815260040161099b906156a9565b611ad06000613df6565b565b600080548190600160a01b900460ff1615611aff5760405162461bcd60e51b815260040161099b90615513565b612710611b19600854600754613e4690919063ffffffff16565b14611b835760405162461bcd60e51b815260206004820152603460248201527f676574526577617264735065725365636f6e643a20496e76616c69642072657760448201527361726420616c6c6f636174696f6e20726174696f60601b606482015260840161099b565b611b8e600754613e52565b9150611b9b600854613ea1565b90509091565b60008054600160a01b900460ff1615611bcc5760405162461bcd60e51b815260040161099b90615513565b6001600160a01b0382166000908152600e602052604090206006546005820154611bf6904261570c565b10611c045750600092915050565b611c27611c1c600654426131a290919063ffffffff16565b6005830154906131a2565b9150505b919050565b6000546001600160a01b03163314611c5a5760405162461bcd60e51b815260040161099b906156a9565b600054600160a01b900460ff1615611c845760405162461bcd60e51b815260040161099b90615513565b611c8c613ede565b6040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b60026001541415611cda5760405162461bcd60e51b815260040161099b9061553d565b60026001556000546001600160a01b03163314611d095760405162461bcd60e51b815260040161099b906156a9565b6001600160a01b038116611d5f5760405162461bcd60e51b815260206004820152601760248201527f4b4f524f4641524d3a20496e76616c696420546f6b656e000000000000000000604482015260640161099b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b03161415611dfb5760405162461bcd60e51b815260206004820152603160248201527f4b4f524f4641524d3a20546f6b656e2063616e6e6f742062652073616d65206160448201527073206b6f726f6d61727520746f6b656e7360781b606482015260840161099b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b03161415611e955760405162461bcd60e51b815260206004820152602f60248201527f4b4f524f4641524d3a20546f6b656e2063616e6e6f742062652073616d65206160448201526e73206661726d656420746f6b656e7360881b606482015260840161099b565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a082319060240160206040518083038186803b158015611ed757600080fd5b505afa158015611eeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f0f91906155ed565b90508015611f2b57611f2b6001600160a01b0383163383613865565b505060018055565b600054600160a01b900460ff1615611f5d5760405162461bcd60e51b815260040161099b90615513565b60026001541415611f805760405162461bcd60e51b815260040161099b9061553d565b600260015580611fd25760405162461bcd60e51b815260206004820152601d60248201527f4b4f524f4641524d3a20496e76616c6964204b6f726f20416d6f756e74000000604482015260640161099b565b600a54811115611ff45760405162461bcd60e51b815260040161099b90615574565b6000612001826000613323565b50509050612020612710610a7b6004548561342f90919063ffffffff16565b336000908152600e6020526040812060030180549091906120429084906155d5565b90915550611f2b90503382613447565b6000546001600160a01b0316331461207c5760405162461bcd60e51b815260040161099b906156a9565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000807f000000000000000000000000000000000000000000000000000000000000000090506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156120ff57600080fd5b505afa158015612113573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121379190615606565b9050600080836001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561217557600080fd5b505afa158015612189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ad919061563a565b506001600160701b031691506001600160701b0316915060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316146122055782612207565b815b61221290600261568a565b9050600061221e613f43565b9050610efe6305f5e100610a7b848461342f565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b15801561229657600080fd5b505afa1580156122aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ce91906155ed565b9050600160095410156122e357600091505090565b60095481106122f457600191505090565b600091505090565b600054600160a01b900460ff16156123265760405162461bcd60e51b815260040161099b90615513565b600260015414156123495760405162461bcd60e51b815260040161099b9061553d565b6002600155336000908152600e6020526040902054806123ab5760405162461bcd60e51b815260206004820152601d60248201527f57697468647261773a20596f752068617665206e6f2062616c616e6365000000604482015260640161099b565b6123b3612929565b5081156123ca576123c381613fd7565b505061246c565b60405163a9059cbb60e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a9059cbb90604401602060405180830381600087803b15801561243257600080fd5b505af1158015612446573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246a9190615723565b505b6124753361408a565b60405181815233907f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243649060200160405180910390a2505060018055565b6000546001600160a01b031633146124dc5760405162461bcd60e51b815260040161099b906156a9565b600955565b6000546001600160a01b0316331461250b5760405162461bcd60e51b815260040161099b906156a9565b6002600154141561252e5760405162461bcd60e51b815260040161099b9061553d565b6002600155346125805760405162461bcd60e51b815260206004820152601c60248201527f4b4f524f4641524d3a20496e76616c69642045746820416d6f756e7400000000604482015260640161099b565b6040513481527f0f2115e51903c319ad6853769c5626af4d72fb85522e0888331f77d618558ef89060200160405180910390a160018055565b600054600160a01b900460ff16156125e35760405162461bcd60e51b815260040161099b90615513565b600260015414156126065760405162461bcd60e51b815260040161099b9061553d565b6002600155346126585760405162461bcd60e51b815260206004820152601c60248201527f4b4f524f4641524d3a20496e76616c69642045746820416d6f756e7400000000604482015260640161099b565b6000612665600080613323565b505090506126733382613447565b5060018055565b6002600154141561269d5760405162461bcd60e51b815260040161099b9061553d565b6002600155336000818152600e60205260409020805490916126ea917f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169190613865565b805460405190815233907f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd96959060200160405180910390a2506040805160c08101825260008082526020808301828152838501838152606085018481526080860185815260a08701868152338752600e9095529690942094518555905160018086019190915590516002850155915160038401559251600483015591516005909101558055565b6000546001600160a01b031633146127ba5760405162461bcd60e51b815260040161099b906156a9565b600380546001600160a01b031916735f4ec3df9cbd43714fe2740f5e3616155c5b8419179055565b6000546001600160a01b0316331461280c5760405162461bcd60e51b815260040161099b906156a9565b6127108111156128775760405162461bcd60e51b815260206004820152603060248201527f736574526577617264416c6c6f636174696f6e733a20496e76616c696420726560448201526f3bb0b932399030b63637b1b0ba34b7b760811b606482015260840161099b565b6007819055612888612710826131a2565b60085550565b6000546001600160a01b031633146128b85760405162461bcd60e51b815260040161099b906156a9565b6001600160a01b03811661291d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161099b565b61292681613df6565b50565b61294d60405180606001604052806000815260200160008152602001600081525090565b600054600160a01b900460ff16156129775760405162461bcd60e51b815260040161099b90615513565b5060408051606081018252600b548152600c546020820152600d548183015290516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b1580156129f757600080fd5b505afa158015612a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2f91906155ed565b90508015612ab257604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015612a9957600080fd5b505af1158015612aad573d6000803e3d6000fd5b505050505b8160400151421115612b9d576000612ac8610f09565b90508015612b83576000612ae98460400151426131a290919063ffffffff16565b90506000612b02612afb600754613e52565b839061342f565b90506000612b1b612b14600854613ea1565b849061342f565b9050612b4984612b378468327cb2734119d3b7a9601e1b61342f565b612b419190615740565b875190613e46565b8652612b7a84612b658368327cb2734119d3b7a9601e1b61342f565b612b6f9190615740565b602088015190613e46565b60208701525050505b5042604083018190528251600b556020830151600c55600d555b5090565b600054600160a01b900460ff1615612bcb5760405162461bcd60e51b815260040161099b90615513565b60026001541415612bee5760405162461bcd60e51b815260040161099b9061553d565b6002600155612bfb612929565b50336000908152600e602052604090206006546005820154612c1d904261570c565b1015612c6b5760405162461bcd60e51b815260206004820152601c60248201527f48617276657374526577617264733a204e6f7420796574207269706500000000604482015260640161099b565b6000806000612cb28460030154612cac866001015461139468327cb2734119d3b7a9601e1b610a7b600b600001548b6000015461342f90919063ffffffff16565b90613e46565b90506000612cf28560040154612cac876002015461139468327cb2734119d3b7a9601e1b610a7b600b600101548c6000015461342f90919063ffffffff16565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b158015612d5757600080fd5b505afa158015612d6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d8f91906155ed565b90508215612de35780831115612dc657612da983826131a2565b6003870155601054612dbb9082613e46565b601055935083612de3565b60006003870155601054612dda9084613e46565b60105591935083915b504780821115612e8b57612df782826131a2565b6004870155600f54612e099082613e46565b600f819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612e6a57600080fd5b505af1158015612e7e573d6000803e3d6000fd5b5050505050809350612f1d565b60006004870155600f54612e9f9083613e46565b600f819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015612f0057600080fd5b505af1158015612f14573d6000803e3d6000fd5b50505050508193505b506000612f2a85856140b3565b50509050612f383382614154565b604080518681526020810186905233917f0e311a2c6dbfb0153ec3a8a5bdca09070b3e5f60768fdc10a20453f38d186873910160405180910390a250506001805550505050565b6001600160a01b0381166000908152600e60205260408120600b54600c548392919083612faa610f09565b600d5490915042118015612fbd57508015155b1561304957600d54600090612fd39042906131a2565b90506000612fe5612afb600754613e52565b90506000612ff7612b14600854613ea1565b905061301d61301685610a7b8568327cb2734119d3b7a9601e1b61342f565b8790613e46565b955061304361303c85610a7b8468327cb2734119d3b7a9601e1b61342f565b8690613e46565b94505050505b6130808460030154612cac866001015461139468327cb2734119d3b7a9601e1b610a7b898b6000015461342f90919063ffffffff16565b95506130b98460040154612cac866002015461139468327cb2734119d3b7a9601e1b610a7b888b6000015461342f90919063ffffffff16565b945050505050915091565b600054600160a01b900460ff16156130ee5760405162461bcd60e51b815260040161099b90615513565b600260015414156131115760405162461bcd60e51b815260040161099b9061553d565b6002600155806131635760405162461bcd60e51b815260206004820152601f60248201527f4b4f524f4641524d3a20496e76616c6964204b6f726f4c5020416d6f756e7400604482015260640161099b565b6131986001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330846133f1565b6126733382613447565b60006131ae828461570c565b9392505050565b80158061323e5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561320457600080fd5b505afa158015613218573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061323c91906155ed565b155b6132a95760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840161099b565b6040516001600160a01b03831660248201526044810182905261163290849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261421d565b606061331b84846000856142ef565b949350505050565b600080600080600061333487614417565b9150915061334061452f565b85156133555761335082826140b3565b61335f565b61335f82826147d1565b91965094509250846133b35760405162461bcd60e51b815260206004820152601860248201527f5a6170496e3a20496e76616c6964204c5020616d6f756e740000000000000000604482015260640161099b565b60405185815233907ff46a0dedafe001f0675ed7387a028988924faa77033feb475b21a00ff5c8b0fa9060200160405180910390a250509250925092565b6040516001600160a01b03808516602483015283166044820152606481018290526134299085906323b872dd60e01b906084016132d5565b50505050565b60006131ae828461568a565b60006131ae8284615740565b61344f612232565b156134955760405162461bcd60e51b815260206004820152601660248201527512d3d493d19054934e8811985c9b481a5cc8199d5b1b60521b604482015260640161099b565b6001600160a01b0382166000908152600e602052604090206134b5612929565b50805415613539576134f98160030154612cac836001015461139468327cb2734119d3b7a9601e1b610a7b600b60000154886000015461342f90919063ffffffff16565b600382015560048101546002820154600c5483546135339392612cac9290916113949168327cb2734119d3b7a9601e1b91610a7b9161342f565b60048201555b80546135459083613e46565b808255600b546135679168327cb2734119d3b7a9601e1b91610a7b919061342f565b6001820155600c54815461358c9168327cb2734119d3b7a9601e1b91610a7b9161342f565b600282015560065460058201546135a3904261570c565b1015806135b05750600654155b156135bc574260058201555b826001600160a01b03167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c836040516135f791815260200190565b60405180910390a2505050565b6000807f000000000000000000000000000000000000000000000000000000000000000090506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561366557600080fd5b505afa158015613679573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061369d9190615606565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316149050600080846001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561371457600080fd5b505afa158015613728573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061374c919061563a565b506001600160701b039182169350169050600061378a7f0000000000000000000000000000000000000000000000000000000000000000600161568a565b6002549091506000906001600160a01b031663054d50d483876137ad57856137af565b865b886137ba57876137bc565b865b6040516001600160e01b031960e086901b16815260048101939093526024830191909152604482015260640160206040518083038186803b15801561380057600080fd5b505afa158015613814573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061383891906155ed565b90506000613844613f43565b90506138586305f5e100610a7b848461342f565b9850505050505050505090565b6040516001600160a01b03831660248201526044810182905261163290849063a9059cbb60e01b906064016132d5565b600054600160a01b900460ff166138e55760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161099b565b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0381166000908152600e60205260409020600654600582015461395c904261570c565b10156139aa5760405162461bcd60e51b815260206004820152601c60248201527f48617276657374526577617264733a204e6f7420796574207269706500000000604482015260640161099b565b60006139e88260030154612cac846001015461139468327cb2734119d3b7a9601e1b610a7b600b60000154896000015461342f90919063ffffffff16565b90506000613a288360040154612cac856002015461139468327cb2734119d3b7a9601e1b610a7b600b600101548a6000015461342f90919063ffffffff16565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b158015613a8d57600080fd5b505afa158015613aa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ac591906155ed565b90508215613bf55780831115613b6b57613b096001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168683613865565b613b1383826131a2565b6003850155601054613b259082613e46565b6010556040518181526001600160a01b038616907f53ddfebde8c1ec45137c3d82fe7bc7430fb2b072e6fa0bf49f913783483e822b9060200160405180910390a2613bf5565b613b9f6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168685613865565b60006003850155601054613bb39084613e46565b6010556040518381526001600160a01b038616907f53ddfebde8c1ec45137c3d82fe7bc7430fb2b072e6fa0bf49f913783483e822b9060200160405180910390a25b504780821115613cd5576000856001600160a01b03168260405160006040518083038185875af1925050503d8060008114613c4c576040519150601f19603f3d011682016040523d82523d6000602084013e613c51565b606091505b5050905080613c725760405162461bcd60e51b815260040161099b906156de565b613c7c83836131a2565b6004860155600f54613c8e9083613e46565b600f556040518281526001600160a01b038716907f266b9e3a9eb2496eb006cf5a0f0c7af08f65afa22ca1ec332db3dde3215cc06c9060200160405180910390a250613d9f565b6000856001600160a01b03168360405160006040518083038185875af1925050503d8060008114613d22576040519150601f19603f3d011682016040523d82523d6000602084013e613d27565b606091505b5050905080613d485760405162461bcd60e51b815260040161099b906156de565b60006004860155600f54613d5c9084613e46565b600f556040518381526001600160a01b038716907f266b9e3a9eb2496eb006cf5a0f0c7af08f65afa22ca1ec332db3dde3215cc06c9060200160405180910390a2505b50600b548354613dc09168327cb2734119d3b7a9601e1b91610a7b9161342f565b6001840155600c548354613de59168327cb2734119d3b7a9601e1b91610a7b9161342f565b600284015550504260059091015550565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006131ae82846155d5565b600080613e5d613604565b90506000613e696148e4565b905061331b612710610a7b84817f0000000000000000000000000000000000000000000000000000000000000000611455878b61342f565b600080613eac613f43565b90506000613eb86148e4565b90506305f5e100613ed5612710610a7b858185611455888c61342f565b95945050505050565b600054600160a01b900460ff1615613f085760405162461bcd60e51b815260040161099b90615513565b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586139153390565b600080600360009054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b158015613f9457600080fd5b505afa158015613fa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fcc919061577c565b509195945050505050565b600080613fe383614904565b6040519193509150600090339083908381818185875af1925050503d806000811461402a576040519150601f19603f3d011682016040523d82523d6000602084013e61402f565b606091505b50509050806140505760405162461bcd60e51b815260040161099b906156de565b6140846001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163385613865565b50915091565b61409381613932565b50336000908152600e602052604081208181556001810182905560020155565b60008060006140c0615443565b6020810186905260408101859052600080806140dc89826147d1565b919450925090506140ed83886155d5565b96506140f982876155d5565b955061410581866155d5565b9450505050600080600061411e600085604001516147d1565b9194509250905061412f83886155d5565b965061413b82876155d5565b955061414781866155d5565b9450505050509250925092565b61415c612232565b156141a25760405162461bcd60e51b815260206004820152601660248201527512d3d493d19054934e8811985c9b481a5cc8199d5b1b60521b604482015260640161099b565b6001600160a01b0382166000908152600e6020526040902080546141c69083613e46565b808255600b546141e89168327cb2734119d3b7a9601e1b91610a7b919061342f565b6001820155600c54815461420d9168327cb2734119d3b7a9601e1b91610a7b9161342f565b6002820155426005909101555050565b6000614272826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661330c9092919063ffffffff16565b80519091501561163257808060200190518101906142909190615723565b6116325760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161099b565b6060824710156143505760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161099b565b843b61439e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161099b565b600080866001600160a01b031685876040516143ba91906157f8565b60006040518083038185875af1925050503d80600081146143f7576040519150601f19603f3d011682016040523d82523d6000602084013e6143fc565b606091505b509150915061440c828286614bfc565b979650505050505050565b6000348015614495577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561447b57600080fd5b505af115801561448f573d6000803e3d6000fd5b50505050505b60013410156144ee57600083116144ee5760405162461bcd60e51b815260206004820152601c60248201527f4b4f524f4641524d3a20496e76616c6964205a6170496e2043616c6c00000000604482015260640161099b565b8215614529576145296001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163330866133f1565b91929050565b600254604051636eb1769f60e11b81523060048201526001600160a01b0391821660248201527f00000000000000000000000000000000000000000000000000000000000000009091169063dd62ed3e9060440160206040518083038186803b15801561459b57600080fd5b505afa1580156145af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145d391906155ed565b6146815760025460405163095ea7b360e01b81526001600160a01b03918216600482015260001960248201527f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b390604401602060405180830381600087803b15801561464757600080fd5b505af115801561465b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061467f9190615723565b505b600254604051636eb1769f60e11b81523060048201526001600160a01b0391821660248201527f00000000000000000000000000000000000000000000000000000000000000009091169063dd62ed3e9060440160206040518083038186803b1580156146ed57600080fd5b505afa158015614701573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061472591906155ed565b611ad05760025460405163095ea7b360e01b81526001600160a01b03918216600482015260001960248201527f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b390604401602060405180830381600087803b15801561479957600080fd5b505af11580156147ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129269190615723565b60008060006147de615443565b60008061480a7f0000000000000000000000000000000000000000000000000000000000000000614c35565b9150915060008811801561481e5750600187105b1561485e57608083018890526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660608401526148aa565b60008711801561486e5750600188105b156148aa57608083018790526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660608401525b6000806148c1856060015185858860800151614d29565b915091506148d184848484614e86565b919c909b50909950975050505050505050565b6000806148ef610abd565b90506148fe816201518061343b565b91505090565b60008061490f61452f565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b15801561497157600080fd5b505afa158015614985573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149a991906155ed565b60025460405163af2979eb60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152602482018890526001604483018190526064830152306084830152600f60fc1b60a483015292935091169063af2979eb9060c401602060405180830381600087803b158015614a3757600080fd5b505af1158015614a4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a6f91906155ed565b915060008211614aba5760405162461bcd60e51b81526020600482015260166024820152755a61704f75743a20457468204f7574707574204c6f7760501b604482015260640161099b565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b158015614b1c57600080fd5b505afa158015614b30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b5491906155ed565b9050818111614ba55760405162461bcd60e51b815260206004820152601960248201527f5a61704f75743a204e6f7468696e6720746f205a61704f757400000000000000604482015260640161099b565b614baf81836131a2565b604080518781526020810183905290810185905290945033907feeb4f1cd73a099727e4fe7efacba511f03191bf19f4c7bd0d6d1745c75a5cfc99060600160405180910390a25050915091565b60608315614c0b5750816131ae565b825115614c1b5782518084602001fd5b8160405162461bcd60e51b815260040161099b9190615814565b6000806000839050806001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015614c7657600080fd5b505afa158015614c8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cae9190615606565b9250806001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015614ce957600080fd5b505afa158015614cfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d219190615606565b915050915091565b60008060007f00000000000000000000000000000000000000000000000000000000000000009050600080826001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015614d8d57600080fd5b505afa158015614da1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614dc5919061563a565b506001600160701b031691506001600160701b03169150876001600160a01b0316896001600160a01b03161415614e3a576000614e028388614fa6565b90506001811015614e1b57614e1887600261343b565b90505b614e268a8983615001565b9450614e3287826131a2565b955050614e7a565b6000614e468288614fa6565b90506001811015614e5f57614e5c87600261343b565b90505b614e6a8a8a83615001565b9550614e7687826131a2565b9450505b50505094509492505050565b60025460009081908190614ea59088906001600160a01b0316876153aa565b600254614ebd9087906001600160a01b0316866153aa565b60025460405162e8e33760e81b81526001600160a01b0389811660048301528881166024830152604482018890526064820187905260016084830181905260a48301523060c4830152600f60fc1b60e4830152600092839283929091169063e8e337009061010401606060405180830381600087803b158015614f3f57600080fd5b505af1158015614f53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f779190615847565b97509093509150859050614f8b88846131a2565b9450614f9787836131a2565b93505050509450945094915050565b60006107ca614fb7846107cd61568a565b614fed614fc786623cda2961568a565b614fd486623cda2061568a565b614fde91906155d5565b614fe8908761568a565b6153d4565b614ff7919061570c565b6131ae9190615740565b6000826001600160a01b0316846001600160a01b031614156150245750806131ae565b60025461504a9085906001600160a01b03166150458564e8d4a5100061342f565b6153aa565b60405163e6a4390560e01b81526001600160a01b03858116600483015284811660248301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063e6a439059060440160206040518083038186803b1580156150b857600080fd5b505afa1580156150cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150f09190615606565b90506001600160a01b0381166151535760405162461bcd60e51b815260206004820152602260248201527f53776170546f6b656e466f72546f6b656e3a205377617020706174682065727260448201526137b960f11b606482015260840161099b565b604080516002808252606082018352600092602083019080368337019050509050858160008151811061518857615188615875565b60200260200101906001600160a01b031690816001600160a01b03168152505084816001815181106151bc576151bc615875565b6001600160a01b0392831660209182029290920101526040516370a0823160e01b81523060048201526000918716906370a082319060240160206040518083038186803b15801561520c57600080fd5b505afa158015615220573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061524491906155ed565b600254604051635c11d79560e01b81529192506001600160a01b031690635c11d7959061528290889060009087903090600f60fc1b9060040161588b565b600060405180830381600087803b15801561529c57600080fd5b505af11580156152b0573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092506001600160a01b03891691506370a082319060240160206040518083038186803b1580156152f657600080fd5b505afa15801561530a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061532e91906155ed565b905061533a81836131a2565b94506000851161539f5760405162461bcd60e51b815260206004820152602a60248201527f53776170546f6b656e466f72546f6b656e3a204572726f72205377617070696e60448201526933902a37b5b2b739901960b11b606482015260840161099b565b505050509392505050565b826153c06001600160a01b0382168460006131b5565b6134296001600160a01b03821684846131b5565b6000600382111561543557508060006153ee600283615740565b6153f99060016155d5565b90505b8181101561542f579050806002816154148186615740565b61541e91906155d5565b6154289190615740565b90506153fc565b50919050565b8115611c2b57506001919050565b6040518060a0016040528060008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000806040838503121561548e57600080fd5b50508035926020909101359150565b6000602082840312156154af57600080fd5b5035919050565b6001600160a01b038116811461292657600080fd5b6000602082840312156154dd57600080fd5b81356131ae816154b6565b801515811461292657600080fd5b60006020828403121561550857600080fd5b81356131ae816154e8565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602b908201527f4b4f524f4641524d3a2043616e2774206465706f736974206d6f72652074686160408201526a1b8816985c08131a5b5a5d60aa1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600082198211156155e8576155e86155bf565b500190565b6000602082840312156155ff57600080fd5b5051919050565b60006020828403121561561857600080fd5b81516131ae816154b6565b80516001600160701b0381168114611c2b57600080fd5b60008060006060848603121561564f57600080fd5b61565884615623565b925061566660208501615623565b9150604084015163ffffffff8116811461567f57600080fd5b809150509250925092565b60008160001904831182151516156156a4576156a46155bf565b500290565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601490820152732330b4b632b2103a379039b2b7321022ba3432b960611b604082015260600190565b60008282101561571e5761571e6155bf565b500390565b60006020828403121561573557600080fd5b81516131ae816154e8565b60008261575d57634e487b7160e01b600052601260045260246000fd5b500490565b805169ffffffffffffffffffff81168114611c2b57600080fd5b600080600080600060a0868803121561579457600080fd5b61579d86615762565b94506020860151935060408601519250606086015191506157c060808701615762565b90509295509295909350565b60005b838110156157e75781810151838201526020016157cf565b838111156134295750506000910152565b6000825161580a8184602087016157cc565b9190910192915050565b60208152600082518060208401526158338160408501602087016157cc565b601f01601f19169190910160400192915050565b60008060006060848603121561585c57600080fd5b8351925060208401519150604084015190509250925092565b634e487b7160e01b600052603260045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156158db5784516001600160a01b0316835293830193918301916001016158b6565b50506001600160a01b0396909616606085015250505060800152939250505056fea2646970667358221220a0fa0cb22191ca5d1b442d1f6bd2484fd66c022a69fee59bf45f61b06b1c0aa064736f6c63430008080033000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff2423651000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c910000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d00000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000006978000000000000000000000000000000000000000000000000000005af3107a4000

Deployed Bytecode

0x6080604052600436106102cd5760003560e01c80637d97a04311610175578063bd30558e116100dc578063e88c681411610095578063f54ca63c1161006f578063f54ca63c146108e5578063f69e20461461091c578063f6ed201714610931578063fa1e1cd71461095157600080fd5b8063e88c681414610871578063eaa0daa9146108a5578063f2fde38b146108c557600080fd5b8063bd30558e146107df578063bdd8e782146107f5578063be5dc462146107fd578063db2e21bc14610831578063df439d0814610846578063e1e4c77d1461085b57600080fd5b806395877f781161012e57806395877f781461074d57806397b3fcaa1461076d5780639d37db4314610782578063a810a54c14610797578063ae38b386146107b7578063b3ac27bf146107d757600080fd5b80637d97a043146106865780638456cb59146106a6578063885a4cd0146106bb57806389c6e7c3146106db5780638da5cb5b1461070f578063956101791461072d57600080fd5b8063360feb80116102345780635ef837bc116101ed57806370ed0ada116101c757806370ed0ada14610614578063715018a614610627578063735de9f71461063c57806376f259b21461065c57600080fd5b80635ef837bc146105965780636102d69b146105b65780636386c1c7146105cc57600080fd5b8063360feb80146104eb5780633f4ba83a1461050157806342f8d36f146105165780634641257d1461053657806354b36f591461054b5780635c975abb1461056b57600080fd5b806310a62bd31161028657806310a62bd314610401578063169dd71d146104165780631959a002146104365780631d49d66c146104865780632d678dae146104c057806333ddd65e146104d557600080fd5b8063072453101461030c5780630747091d1461032157806309434f28146103495780630ae2bac61461038b5780630af88b24146103a05780630f21dc86146103ec57600080fd5b36610307576040513481527f0f2115e51903c319ad6853769c5626af4d72fb85522e0888331f77d618558ef89060200160405180910390a1005b600080fd5b61031f61031a36600461547b565b610971565b005b34801561032d57600080fd5b50610336610abd565b6040519081526020015b60405180910390f35b34801561035557600080fd5b5061035e610c56565b604080519687526020870195909552938501929092526060840152608083015260a082015260c001610340565b34801561039757600080fd5b50610336610d24565b3480156103ac57600080fd5b506103d47f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6040516001600160a01b039091168152602001610340565b3480156103f857600080fd5b50610336610f09565b34801561040d57600080fd5b50610336611059565b34801561042257600080fd5b5061031f61043136600461549d565b611469565b34801561044257600080fd5b5061035e6104513660046154cb565b600e60205260009081526040902080546001820154600283015460038401546004850154600590950154939492939192909186565b34801561049257600080fd5b50600b54600c54600d546104a592919083565b60408051938452602084019290925290820152606001610340565b3480156104cc57600080fd5b5061031f611498565b3480156104e157600080fd5b50610336600f5481565b3480156104f757600080fd5b5061033660075481565b34801561050d57600080fd5b5061031f611638565b34801561052257600080fd5b5061031f61053136600461549d565b6116e5565b34801561054257600080fd5b5061031f6117af565b34801561055757600080fd5b5061031f61056636600461549d565b611819565b34801561057757600080fd5b50600054600160a01b900460ff165b6040519015158152602001610340565b3480156105a257600080fd5b5061031f6105b136600461549d565b611873565b3480156105c257600080fd5b5061033660085481565b3480156105d857600080fd5b506105ec6105e73660046154cb565b611981565b604080519586526020860194909452928401919091526060830152608082015260a001610340565b34801561062057600080fd5b5047610336565b34801561063357600080fd5b5061031f611a9c565b34801561064857600080fd5b506002546103d4906001600160a01b031681565b34801561066857600080fd5b50610671611ad2565b60408051928352602083019190915201610340565b34801561069257600080fd5b506103366106a13660046154cb565b611ba1565b3480156106b257600080fd5b5061031f611c30565b3480156106c757600080fd5b5061031f6106d63660046154cb565b611cb7565b3480156106e757600080fd5b506103d47f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff242365181565b34801561071b57600080fd5b506000546001600160a01b03166103d4565b34801561073957600080fd5b5061031f61074836600461549d565b611f33565b34801561075957600080fd5b5061031f6107683660046154cb565b612052565b34801561077957600080fd5b5061033661209e565b34801561078e57600080fd5b50610586612232565b3480156107a357600080fd5b5061031f6107b23660046154f6565b6122fc565b3480156107c357600080fd5b5061031f6107d236600461549d565b6124b2565b61031f6124e1565b3480156107eb57600080fd5b5061033660055481565b61031f6125b9565b34801561080957600080fd5b506103d47f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c9181565b34801561083d57600080fd5b5061031f61267a565b34801561085257600080fd5b5061031f612790565b34801561086757600080fd5b5061033660105481565b34801561087d57600080fd5b506103d47f0000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f81565b3480156108b157600080fd5b5061031f6108c036600461549d565b6127e2565b3480156108d157600080fd5b5061031f6108e03660046154cb565b61288e565b3480156108f157600080fd5b506108fa612929565b6040805182518152602080840151908201529181015190820152606001610340565b34801561092857600080fd5b5061031f612ba1565b34801561093d57600080fd5b5061067161094c3660046154cb565b612f7f565b34801561095d57600080fd5b5061031f61096c36600461549d565b6130c4565b600054600160a01b900460ff16156109a45760405162461bcd60e51b815260040161099b90615513565b60405180910390fd5b600260015414156109c75760405162461bcd60e51b815260040161099b9061553d565b6002600155600a548211156109ee5760405162461bcd60e51b815260040161099b90615574565b6000803411610a0757610a02836000613323565b610a12565b610a12836001613323565b50909150508115610a5257610a526001600160a01b037f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c91163330856133f1565b6000610a5e83836155d5565b9050610a81612710610a7b6004548761342f90919063ffffffff16565b9061343b565b336000908152600e602052604081206003018054909190610aa39084906155d5565b90915550610ab390503382613447565b5050600180555050565b60008054600160a01b900460ff1615610ae85760405162461bcd60e51b815260040161099b90615513565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c916001600160a01b0316906370a082319060240160206040518083038186803b158015610b4a57600080fd5b505afa158015610b5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8291906155ed565b905060007f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c916001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610bdf57600080fd5b505afa158015610bf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1791906155ed565b90506000610c3182610a7b610c2a610d24565b869061342f565b9050610c4e612710610a7b8360055461342f90919063ffffffff16565b935050505090565b600080600080600080610c67610f09565b6040516370a0823160e01b81523060048201529096507f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c916001600160a01b0316906370a082319060240160206040518083038186803b158015610cc957600080fd5b505afa158015610cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0191906155ed565b9450610d0b611059565b9350600554925060085491506007549050909192939495565b60008054600160a01b900460ff1615610d4f5760405162461bcd60e51b815260040161099b90615513565b60007f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c9190506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015610daf57600080fd5b505afa158015610dc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de79190615606565b9050600080836001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015610e2557600080fd5b505afa158015610e39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5d919061563a565b506001600160701b031691506001600160701b0316915060007f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff24236516001600160a01b0316846001600160a01b031614610eb55781610eb7565b825b610ec290600261568a565b90506000610ece613604565b9050610efe7f000000000000000000000000000000000000000000000000000000003b9aca00610a7b848461342f565b965050505050505090565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c9116906370a082319060240160206040518083038186803b158015610f6d57600080fd5b505afa158015610f81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa591906155ed565b905060007f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c916001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561100257600080fd5b505afa158015611016573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103a91906155ed565b905061105281610a7b61104b610d24565b859061342f565b9250505090565b60008061dead905060007f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c9190506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156110c157600080fd5b505afa1580156110d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f99190615606565b9050600080836001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561113757600080fd5b505afa15801561114b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116f919061563a565b506001600160701b031691506001600160701b0316915060007f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff24236516001600160a01b0316846001600160a01b0316146111c757816111c9565b825b905060007f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c916001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561122657600080fd5b505afa15801561123a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125e91906155ed565b6040516370a0823160e01b81526001600160a01b03898116600483015291925060009161139a917f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff2423651909116906370a082319060240160206040518083038186803b1580156112cb57600080fd5b505afa1580156112df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130391906155ed565b7f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff24236516001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561135c57600080fd5b505afa158015611370573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139491906155ed565b906131a2565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c9116906370a082319060240160206040518083038186803b1580156113ff57600080fd5b505afa158015611413573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061143791906155ed565b905061145b82610a7b8581670de0b6b3a7640000611455878b61342f565b9061342f565b995050505050505050505090565b6000546001600160a01b031633146114935760405162461bcd60e51b815260040161099b906156a9565b600455565b6000546001600160a01b031633146114c25760405162461bcd60e51b815260040161099b906156a9565b600054600160a01b900460ff16156114ec5760405162461bcd60e51b815260040161099b90615513565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff24236516001600160a01b0316906370a082319060240160206040518083038186803b15801561154e57600080fd5b505afa158015611562573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158691906155ed565b9050303181156115c4576115c46001600160a01b037f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff2423651163384613865565b801561163457604051600090339083908381818185875af1925050503d806000811461160c576040519150601f19603f3d011682016040523d82523d6000602084013e611611565b606091505b50509050806116325760405162461bcd60e51b815260040161099b906156de565b505b5050565b6000546001600160a01b031633146116625760405162461bcd60e51b815260040161099b906156a9565b600054600160a01b900460ff166116b25760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161099b565b6116ba613895565b6040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d1693390600090a1565b6000546001600160a01b0316331461170f5760405162461bcd60e51b815260040161099b906156a9565b611717612929565b5061271081111561176a5760405162461bcd60e51b815260206004820152601e60248201527f5365744461696c794150523a20496e76616c6964204150522056616c75650000604482015260640161099b565b600580549082905560408051828152602081018490527fd2d659d197cf77652feb866d2a49b71684b0e7b0d92bde0b26163f77e2e25a2d910160405180910390a15050565b600054600160a01b900460ff16156117d95760405162461bcd60e51b815260040161099b90615513565b600260015414156117fc5760405162461bcd60e51b815260040161099b9061553d565b6002600155611809612929565b5061181333613932565b60018055565b6000546001600160a01b031633146118435760405162461bcd60e51b815260040161099b906156a9565b61186d7f000000000000000000000000000000000000000000000000000000003b9aca008261568a565b600a5550565b6000546001600160a01b0316331461189d5760405162461bcd60e51b815260040161099b906156a9565b600260015414156118c05760405162461bcd60e51b815260040161099b9061553d565b6002600155806119125760405162461bcd60e51b815260206004820152601d60248201527f4b4f524f4641524d3a20496e76616c6964204b6f726f20416d6f756e74000000604482015260640161099b565b6119476001600160a01b037f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff2423651163330846133f1565b6040518181527fbcb2ea58f5b99aef9322cfc4dc10e836fa7b8bb0d698199d1cb6207f9264eb569060200160405180910390a15060018055565b6001600160a01b0381166000908152600e6020526040812054908080806119a786611ba1565b92506119b286612f7f565b6040516370a0823160e01b815230600482015291935091506000907f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c916001600160a01b0316906370a082319060240160206040518083038186803b158015611a1957600080fd5b505afa158015611a2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5191906155ed565b905060008111611a62576000611a90565b611a9081610a7b611a71610f09565b6001600160a01b038b166000908152600e60205260409020549061342f565b94505091939590929450565b6000546001600160a01b03163314611ac65760405162461bcd60e51b815260040161099b906156a9565b611ad06000613df6565b565b600080548190600160a01b900460ff1615611aff5760405162461bcd60e51b815260040161099b90615513565b612710611b19600854600754613e4690919063ffffffff16565b14611b835760405162461bcd60e51b815260206004820152603460248201527f676574526577617264735065725365636f6e643a20496e76616c69642072657760448201527361726420616c6c6f636174696f6e20726174696f60601b606482015260840161099b565b611b8e600754613e52565b9150611b9b600854613ea1565b90509091565b60008054600160a01b900460ff1615611bcc5760405162461bcd60e51b815260040161099b90615513565b6001600160a01b0382166000908152600e602052604090206006546005820154611bf6904261570c565b10611c045750600092915050565b611c27611c1c600654426131a290919063ffffffff16565b6005830154906131a2565b9150505b919050565b6000546001600160a01b03163314611c5a5760405162461bcd60e51b815260040161099b906156a9565b600054600160a01b900460ff1615611c845760405162461bcd60e51b815260040161099b90615513565b611c8c613ede565b6040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e75290600090a1565b60026001541415611cda5760405162461bcd60e51b815260040161099b9061553d565b60026001556000546001600160a01b03163314611d095760405162461bcd60e51b815260040161099b906156a9565b6001600160a01b038116611d5f5760405162461bcd60e51b815260206004820152601760248201527f4b4f524f4641524d3a20496e76616c696420546f6b656e000000000000000000604482015260640161099b565b7f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff24236516001600160a01b0316816001600160a01b03161415611dfb5760405162461bcd60e51b815260206004820152603160248201527f4b4f524f4641524d3a20546f6b656e2063616e6e6f742062652073616d65206160448201527073206b6f726f6d61727520746f6b656e7360781b606482015260840161099b565b7f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c916001600160a01b0316816001600160a01b03161415611e955760405162461bcd60e51b815260206004820152602f60248201527f4b4f524f4641524d3a20546f6b656e2063616e6e6f742062652073616d65206160448201526e73206661726d656420746f6b656e7360881b606482015260840161099b565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a082319060240160206040518083038186803b158015611ed757600080fd5b505afa158015611eeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f0f91906155ed565b90508015611f2b57611f2b6001600160a01b0383163383613865565b505060018055565b600054600160a01b900460ff1615611f5d5760405162461bcd60e51b815260040161099b90615513565b60026001541415611f805760405162461bcd60e51b815260040161099b9061553d565b600260015580611fd25760405162461bcd60e51b815260206004820152601d60248201527f4b4f524f4641524d3a20496e76616c6964204b6f726f20416d6f756e74000000604482015260640161099b565b600a54811115611ff45760405162461bcd60e51b815260040161099b90615574565b6000612001826000613323565b50509050612020612710610a7b6004548561342f90919063ffffffff16565b336000908152600e6020526040812060030180549091906120429084906155d5565b90915550611f2b90503382613447565b6000546001600160a01b0316331461207c5760405162461bcd60e51b815260040161099b906156a9565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000807f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c9190506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b1580156120ff57600080fd5b505afa158015612113573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121379190615606565b9050600080836001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561217557600080fd5b505afa158015612189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ad919061563a565b506001600160701b031691506001600160701b0316915060007f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff24236516001600160a01b0316846001600160a01b0316146122055782612207565b815b61221290600261568a565b9050600061221e613f43565b9050610efe6305f5e100610a7b848461342f565b6040516370a0823160e01b815230600482015260009081906001600160a01b037f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c9116906370a082319060240160206040518083038186803b15801561229657600080fd5b505afa1580156122aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ce91906155ed565b9050600160095410156122e357600091505090565b60095481106122f457600191505090565b600091505090565b600054600160a01b900460ff16156123265760405162461bcd60e51b815260040161099b90615513565b600260015414156123495760405162461bcd60e51b815260040161099b9061553d565b6002600155336000908152600e6020526040902054806123ab5760405162461bcd60e51b815260206004820152601d60248201527f57697468647261773a20596f752068617665206e6f2062616c616e6365000000604482015260640161099b565b6123b3612929565b5081156123ca576123c381613fd7565b505061246c565b60405163a9059cbb60e01b8152336004820152602481018290527f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c916001600160a01b03169063a9059cbb90604401602060405180830381600087803b15801561243257600080fd5b505af1158015612446573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246a9190615723565b505b6124753361408a565b60405181815233907f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a94243649060200160405180910390a2505060018055565b6000546001600160a01b031633146124dc5760405162461bcd60e51b815260040161099b906156a9565b600955565b6000546001600160a01b0316331461250b5760405162461bcd60e51b815260040161099b906156a9565b6002600154141561252e5760405162461bcd60e51b815260040161099b9061553d565b6002600155346125805760405162461bcd60e51b815260206004820152601c60248201527f4b4f524f4641524d3a20496e76616c69642045746820416d6f756e7400000000604482015260640161099b565b6040513481527f0f2115e51903c319ad6853769c5626af4d72fb85522e0888331f77d618558ef89060200160405180910390a160018055565b600054600160a01b900460ff16156125e35760405162461bcd60e51b815260040161099b90615513565b600260015414156126065760405162461bcd60e51b815260040161099b9061553d565b6002600155346126585760405162461bcd60e51b815260206004820152601c60248201527f4b4f524f4641524d3a20496e76616c69642045746820416d6f756e7400000000604482015260640161099b565b6000612665600080613323565b505090506126733382613447565b5060018055565b6002600154141561269d5760405162461bcd60e51b815260040161099b9061553d565b6002600155336000818152600e60205260409020805490916126ea917f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c916001600160a01b03169190613865565b805460405190815233907f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd96959060200160405180910390a2506040805160c08101825260008082526020808301828152838501838152606085018481526080860185815260a08701868152338752600e9095529690942094518555905160018086019190915590516002850155915160038401559251600483015591516005909101558055565b6000546001600160a01b031633146127ba5760405162461bcd60e51b815260040161099b906156a9565b600380546001600160a01b031916735f4ec3df9cbd43714fe2740f5e3616155c5b8419179055565b6000546001600160a01b0316331461280c5760405162461bcd60e51b815260040161099b906156a9565b6127108111156128775760405162461bcd60e51b815260206004820152603060248201527f736574526577617264416c6c6f636174696f6e733a20496e76616c696420726560448201526f3bb0b932399030b63637b1b0ba34b7b760811b606482015260840161099b565b6007819055612888612710826131a2565b60085550565b6000546001600160a01b031633146128b85760405162461bcd60e51b815260040161099b906156a9565b6001600160a01b03811661291d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161099b565b61292681613df6565b50565b61294d60405180606001604052806000815260200160008152602001600081525090565b600054600160a01b900460ff16156129775760405162461bcd60e51b815260040161099b90615513565b5060408051606081018252600b548152600c546020820152600d548183015290516370a0823160e01b81523060048201526000907f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b0316906370a082319060240160206040518083038186803b1580156129f757600080fd5b505afa158015612a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a2f91906155ed565b90508015612ab257604051632e1a7d4d60e01b8152600481018290527f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015612a9957600080fd5b505af1158015612aad573d6000803e3d6000fd5b505050505b8160400151421115612b9d576000612ac8610f09565b90508015612b83576000612ae98460400151426131a290919063ffffffff16565b90506000612b02612afb600754613e52565b839061342f565b90506000612b1b612b14600854613ea1565b849061342f565b9050612b4984612b378468327cb2734119d3b7a9601e1b61342f565b612b419190615740565b875190613e46565b8652612b7a84612b658368327cb2734119d3b7a9601e1b61342f565b612b6f9190615740565b602088015190613e46565b60208701525050505b5042604083018190528251600b556020830151600c55600d555b5090565b600054600160a01b900460ff1615612bcb5760405162461bcd60e51b815260040161099b90615513565b60026001541415612bee5760405162461bcd60e51b815260040161099b9061553d565b6002600155612bfb612929565b50336000908152600e602052604090206006546005820154612c1d904261570c565b1015612c6b5760405162461bcd60e51b815260206004820152601c60248201527f48617276657374526577617264733a204e6f7420796574207269706500000000604482015260640161099b565b6000806000612cb28460030154612cac866001015461139468327cb2734119d3b7a9601e1b610a7b600b600001548b6000015461342f90919063ffffffff16565b90613e46565b90506000612cf28560040154612cac876002015461139468327cb2734119d3b7a9601e1b610a7b600b600101548c6000015461342f90919063ffffffff16565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff242365116906370a082319060240160206040518083038186803b158015612d5757600080fd5b505afa158015612d6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d8f91906155ed565b90508215612de35780831115612dc657612da983826131a2565b6003870155601054612dbb9082613e46565b601055935083612de3565b60006003870155601054612dda9084613e46565b60105591935083915b504780821115612e8b57612df782826131a2565b6004870155600f54612e099082613e46565b600f819055507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612e6a57600080fd5b505af1158015612e7e573d6000803e3d6000fd5b5050505050809350612f1d565b60006004870155600f54612e9f9083613e46565b600f819055507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b158015612f0057600080fd5b505af1158015612f14573d6000803e3d6000fd5b50505050508193505b506000612f2a85856140b3565b50509050612f383382614154565b604080518681526020810186905233917f0e311a2c6dbfb0153ec3a8a5bdca09070b3e5f60768fdc10a20453f38d186873910160405180910390a250506001805550505050565b6001600160a01b0381166000908152600e60205260408120600b54600c548392919083612faa610f09565b600d5490915042118015612fbd57508015155b1561304957600d54600090612fd39042906131a2565b90506000612fe5612afb600754613e52565b90506000612ff7612b14600854613ea1565b905061301d61301685610a7b8568327cb2734119d3b7a9601e1b61342f565b8790613e46565b955061304361303c85610a7b8468327cb2734119d3b7a9601e1b61342f565b8690613e46565b94505050505b6130808460030154612cac866001015461139468327cb2734119d3b7a9601e1b610a7b898b6000015461342f90919063ffffffff16565b95506130b98460040154612cac866002015461139468327cb2734119d3b7a9601e1b610a7b888b6000015461342f90919063ffffffff16565b945050505050915091565b600054600160a01b900460ff16156130ee5760405162461bcd60e51b815260040161099b90615513565b600260015414156131115760405162461bcd60e51b815260040161099b9061553d565b6002600155806131635760405162461bcd60e51b815260206004820152601f60248201527f4b4f524f4641524d3a20496e76616c6964204b6f726f4c5020416d6f756e7400604482015260640161099b565b6131986001600160a01b037f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c91163330846133f1565b6126733382613447565b60006131ae828461570c565b9392505050565b80158061323e5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b15801561320457600080fd5b505afa158015613218573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061323c91906155ed565b155b6132a95760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606482015260840161099b565b6040516001600160a01b03831660248201526044810182905261163290849063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261421d565b606061331b84846000856142ef565b949350505050565b600080600080600061333487614417565b9150915061334061452f565b85156133555761335082826140b3565b61335f565b61335f82826147d1565b91965094509250846133b35760405162461bcd60e51b815260206004820152601860248201527f5a6170496e3a20496e76616c6964204c5020616d6f756e740000000000000000604482015260640161099b565b60405185815233907ff46a0dedafe001f0675ed7387a028988924faa77033feb475b21a00ff5c8b0fa9060200160405180910390a250509250925092565b6040516001600160a01b03808516602483015283166044820152606481018290526134299085906323b872dd60e01b906084016132d5565b50505050565b60006131ae828461568a565b60006131ae8284615740565b61344f612232565b156134955760405162461bcd60e51b815260206004820152601660248201527512d3d493d19054934e8811985c9b481a5cc8199d5b1b60521b604482015260640161099b565b6001600160a01b0382166000908152600e602052604090206134b5612929565b50805415613539576134f98160030154612cac836001015461139468327cb2734119d3b7a9601e1b610a7b600b60000154886000015461342f90919063ffffffff16565b600382015560048101546002820154600c5483546135339392612cac9290916113949168327cb2734119d3b7a9601e1b91610a7b9161342f565b60048201555b80546135459083613e46565b808255600b546135679168327cb2734119d3b7a9601e1b91610a7b919061342f565b6001820155600c54815461358c9168327cb2734119d3b7a9601e1b91610a7b9161342f565b600282015560065460058201546135a3904261570c565b1015806135b05750600654155b156135bc574260058201555b826001600160a01b03167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c836040516135f791815260200190565b60405180910390a2505050565b6000807f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c9190506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561366557600080fd5b505afa158015613679573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061369d9190615606565b905060007f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff24236516001600160a01b0316826001600160a01b0316149050600080846001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561371457600080fd5b505afa158015613728573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061374c919061563a565b506001600160701b039182169350169050600061378a7f000000000000000000000000000000000000000000000000000000003b9aca00600161568a565b6002549091506000906001600160a01b031663054d50d483876137ad57856137af565b865b886137ba57876137bc565b865b6040516001600160e01b031960e086901b16815260048101939093526024830191909152604482015260640160206040518083038186803b15801561380057600080fd5b505afa158015613814573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061383891906155ed565b90506000613844613f43565b90506138586305f5e100610a7b848461342f565b9850505050505050505090565b6040516001600160a01b03831660248201526044810182905261163290849063a9059cbb60e01b906064016132d5565b600054600160a01b900460ff166138e55760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161099b565b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b0381166000908152600e60205260409020600654600582015461395c904261570c565b10156139aa5760405162461bcd60e51b815260206004820152601c60248201527f48617276657374526577617264733a204e6f7420796574207269706500000000604482015260640161099b565b60006139e88260030154612cac846001015461139468327cb2734119d3b7a9601e1b610a7b600b60000154896000015461342f90919063ffffffff16565b90506000613a288360040154612cac856002015461139468327cb2734119d3b7a9601e1b610a7b600b600101548a6000015461342f90919063ffffffff16565b6040516370a0823160e01b81523060048201529091506000906001600160a01b037f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff242365116906370a082319060240160206040518083038186803b158015613a8d57600080fd5b505afa158015613aa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ac591906155ed565b90508215613bf55780831115613b6b57613b096001600160a01b037f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff2423651168683613865565b613b1383826131a2565b6003850155601054613b259082613e46565b6010556040518181526001600160a01b038616907f53ddfebde8c1ec45137c3d82fe7bc7430fb2b072e6fa0bf49f913783483e822b9060200160405180910390a2613bf5565b613b9f6001600160a01b037f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff2423651168685613865565b60006003850155601054613bb39084613e46565b6010556040518381526001600160a01b038616907f53ddfebde8c1ec45137c3d82fe7bc7430fb2b072e6fa0bf49f913783483e822b9060200160405180910390a25b504780821115613cd5576000856001600160a01b03168260405160006040518083038185875af1925050503d8060008114613c4c576040519150601f19603f3d011682016040523d82523d6000602084013e613c51565b606091505b5050905080613c725760405162461bcd60e51b815260040161099b906156de565b613c7c83836131a2565b6004860155600f54613c8e9083613e46565b600f556040518281526001600160a01b038716907f266b9e3a9eb2496eb006cf5a0f0c7af08f65afa22ca1ec332db3dde3215cc06c9060200160405180910390a250613d9f565b6000856001600160a01b03168360405160006040518083038185875af1925050503d8060008114613d22576040519150601f19603f3d011682016040523d82523d6000602084013e613d27565b606091505b5050905080613d485760405162461bcd60e51b815260040161099b906156de565b60006004860155600f54613d5c9084613e46565b600f556040518381526001600160a01b038716907f266b9e3a9eb2496eb006cf5a0f0c7af08f65afa22ca1ec332db3dde3215cc06c9060200160405180910390a2505b50600b548354613dc09168327cb2734119d3b7a9601e1b91610a7b9161342f565b6001840155600c548354613de59168327cb2734119d3b7a9601e1b91610a7b9161342f565b600284015550504260059091015550565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006131ae82846155d5565b600080613e5d613604565b90506000613e696148e4565b905061331b612710610a7b84817f000000000000000000000000000000000000000000000000000000003b9aca00611455878b61342f565b600080613eac613f43565b90506000613eb86148e4565b90506305f5e100613ed5612710610a7b858185611455888c61342f565b95945050505050565b600054600160a01b900460ff1615613f085760405162461bcd60e51b815260040161099b90615513565b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586139153390565b600080600360009054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b158015613f9457600080fd5b505afa158015613fa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fcc919061577c565b509195945050505050565b600080613fe383614904565b6040519193509150600090339083908381818185875af1925050503d806000811461402a576040519150601f19603f3d011682016040523d82523d6000602084013e61402f565b606091505b50509050806140505760405162461bcd60e51b815260040161099b906156de565b6140846001600160a01b037f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff2423651163385613865565b50915091565b61409381613932565b50336000908152600e602052604081208181556001810182905560020155565b60008060006140c0615443565b6020810186905260408101859052600080806140dc89826147d1565b919450925090506140ed83886155d5565b96506140f982876155d5565b955061410581866155d5565b9450505050600080600061411e600085604001516147d1565b9194509250905061412f83886155d5565b965061413b82876155d5565b955061414781866155d5565b9450505050509250925092565b61415c612232565b156141a25760405162461bcd60e51b815260206004820152601660248201527512d3d493d19054934e8811985c9b481a5cc8199d5b1b60521b604482015260640161099b565b6001600160a01b0382166000908152600e6020526040902080546141c69083613e46565b808255600b546141e89168327cb2734119d3b7a9601e1b91610a7b919061342f565b6001820155600c54815461420d9168327cb2734119d3b7a9601e1b91610a7b9161342f565b6002820155426005909101555050565b6000614272826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661330c9092919063ffffffff16565b80519091501561163257808060200190518101906142909190615723565b6116325760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161099b565b6060824710156143505760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161099b565b843b61439e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161099b565b600080866001600160a01b031685876040516143ba91906157f8565b60006040518083038185875af1925050503d80600081146143f7576040519150601f19603f3d011682016040523d82523d6000602084013e6143fc565b606091505b509150915061440c828286614bfc565b979650505050505050565b6000348015614495577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561447b57600080fd5b505af115801561448f573d6000803e3d6000fd5b50505050505b60013410156144ee57600083116144ee5760405162461bcd60e51b815260206004820152601c60248201527f4b4f524f4641524d3a20496e76616c6964205a6170496e2043616c6c00000000604482015260640161099b565b8215614529576145296001600160a01b037f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff2423651163330866133f1565b91929050565b600254604051636eb1769f60e11b81523060048201526001600160a01b0391821660248201527f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff24236519091169063dd62ed3e9060440160206040518083038186803b15801561459b57600080fd5b505afa1580156145af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145d391906155ed565b6146815760025460405163095ea7b360e01b81526001600160a01b03918216600482015260001960248201527f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff24236519091169063095ea7b390604401602060405180830381600087803b15801561464757600080fd5b505af115801561465b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061467f9190615723565b505b600254604051636eb1769f60e11b81523060048201526001600160a01b0391821660248201527f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c919091169063dd62ed3e9060440160206040518083038186803b1580156146ed57600080fd5b505afa158015614701573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061472591906155ed565b611ad05760025460405163095ea7b360e01b81526001600160a01b03918216600482015260001960248201527f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c919091169063095ea7b390604401602060405180830381600087803b15801561479957600080fd5b505af11580156147ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129269190615723565b60008060006147de615443565b60008061480a7f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c91614c35565b9150915060008811801561481e5750600187105b1561485e57608083018890526001600160a01b037f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff24236511660608401526148aa565b60008711801561486e5750600188105b156148aa57608083018790526001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21660608401525b6000806148c1856060015185858860800151614d29565b915091506148d184848484614e86565b919c909b50909950975050505050505050565b6000806148ef610abd565b90506148fe816201518061343b565b91505090565b60008061490f61452f565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff24236516001600160a01b0316906370a082319060240160206040518083038186803b15801561497157600080fd5b505afa158015614985573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149a991906155ed565b60025460405163af2979eb60e01b81526001600160a01b037f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff242365181166004830152602482018890526001604483018190526064830152306084830152600f60fc1b60a483015292935091169063af2979eb9060c401602060405180830381600087803b158015614a3757600080fd5b505af1158015614a4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a6f91906155ed565b915060008211614aba5760405162461bcd60e51b81526020600482015260166024820152755a61704f75743a20457468204f7574707574204c6f7760501b604482015260640161099b565b6040516370a0823160e01b81523060048201526000907f000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff24236516001600160a01b0316906370a082319060240160206040518083038186803b158015614b1c57600080fd5b505afa158015614b30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b5491906155ed565b9050818111614ba55760405162461bcd60e51b815260206004820152601960248201527f5a61704f75743a204e6f7468696e6720746f205a61704f757400000000000000604482015260640161099b565b614baf81836131a2565b604080518781526020810183905290810185905290945033907feeb4f1cd73a099727e4fe7efacba511f03191bf19f4c7bd0d6d1745c75a5cfc99060600160405180910390a25050915091565b60608315614c0b5750816131ae565b825115614c1b5782518084602001fd5b8160405162461bcd60e51b815260040161099b9190615814565b6000806000839050806001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b158015614c7657600080fd5b505afa158015614c8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614cae9190615606565b9250806001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b158015614ce957600080fd5b505afa158015614cfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d219190615606565b915050915091565b60008060007f000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c919050600080826001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015614d8d57600080fd5b505afa158015614da1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614dc5919061563a565b506001600160701b031691506001600160701b03169150876001600160a01b0316896001600160a01b03161415614e3a576000614e028388614fa6565b90506001811015614e1b57614e1887600261343b565b90505b614e268a8983615001565b9450614e3287826131a2565b955050614e7a565b6000614e468288614fa6565b90506001811015614e5f57614e5c87600261343b565b90505b614e6a8a8a83615001565b9550614e7687826131a2565b9450505b50505094509492505050565b60025460009081908190614ea59088906001600160a01b0316876153aa565b600254614ebd9087906001600160a01b0316866153aa565b60025460405162e8e33760e81b81526001600160a01b0389811660048301528881166024830152604482018890526064820187905260016084830181905260a48301523060c4830152600f60fc1b60e4830152600092839283929091169063e8e337009061010401606060405180830381600087803b158015614f3f57600080fd5b505af1158015614f53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f779190615847565b97509093509150859050614f8b88846131a2565b9450614f9787836131a2565b93505050509450945094915050565b60006107ca614fb7846107cd61568a565b614fed614fc786623cda2961568a565b614fd486623cda2061568a565b614fde91906155d5565b614fe8908761568a565b6153d4565b614ff7919061570c565b6131ae9190615740565b6000826001600160a01b0316846001600160a01b031614156150245750806131ae565b60025461504a9085906001600160a01b03166150458564e8d4a5100061342f565b6153aa565b60405163e6a4390560e01b81526001600160a01b03858116600483015284811660248301526000917f0000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f9091169063e6a439059060440160206040518083038186803b1580156150b857600080fd5b505afa1580156150cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906150f09190615606565b90506001600160a01b0381166151535760405162461bcd60e51b815260206004820152602260248201527f53776170546f6b656e466f72546f6b656e3a205377617020706174682065727260448201526137b960f11b606482015260840161099b565b604080516002808252606082018352600092602083019080368337019050509050858160008151811061518857615188615875565b60200260200101906001600160a01b031690816001600160a01b03168152505084816001815181106151bc576151bc615875565b6001600160a01b0392831660209182029290920101526040516370a0823160e01b81523060048201526000918716906370a082319060240160206040518083038186803b15801561520c57600080fd5b505afa158015615220573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061524491906155ed565b600254604051635c11d79560e01b81529192506001600160a01b031690635c11d7959061528290889060009087903090600f60fc1b9060040161588b565b600060405180830381600087803b15801561529c57600080fd5b505af11580156152b0573d6000803e3d6000fd5b50506040516370a0823160e01b8152306004820152600092506001600160a01b03891691506370a082319060240160206040518083038186803b1580156152f657600080fd5b505afa15801561530a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061532e91906155ed565b905061533a81836131a2565b94506000851161539f5760405162461bcd60e51b815260206004820152602a60248201527f53776170546f6b656e466f72546f6b656e3a204572726f72205377617070696e60448201526933902a37b5b2b739901960b11b606482015260840161099b565b505050509392505050565b826153c06001600160a01b0382168460006131b5565b6134296001600160a01b03821684846131b5565b6000600382111561543557508060006153ee600283615740565b6153f99060016155d5565b90505b8181101561542f579050806002816154148186615740565b61541e91906155d5565b6154289190615740565b90506153fc565b50919050565b8115611c2b57506001919050565b6040518060a0016040528060008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000806040838503121561548e57600080fd5b50508035926020909101359150565b6000602082840312156154af57600080fd5b5035919050565b6001600160a01b038116811461292657600080fd5b6000602082840312156154dd57600080fd5b81356131ae816154b6565b801515811461292657600080fd5b60006020828403121561550857600080fd5b81356131ae816154e8565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602b908201527f4b4f524f4641524d3a2043616e2774206465706f736974206d6f72652074686160408201526a1b8816985c08131a5b5a5d60aa1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600082198211156155e8576155e86155bf565b500190565b6000602082840312156155ff57600080fd5b5051919050565b60006020828403121561561857600080fd5b81516131ae816154b6565b80516001600160701b0381168114611c2b57600080fd5b60008060006060848603121561564f57600080fd5b61565884615623565b925061566660208501615623565b9150604084015163ffffffff8116811461567f57600080fd5b809150509250925092565b60008160001904831182151516156156a4576156a46155bf565b500290565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601490820152732330b4b632b2103a379039b2b7321022ba3432b960611b604082015260600190565b60008282101561571e5761571e6155bf565b500390565b60006020828403121561573557600080fd5b81516131ae816154e8565b60008261575d57634e487b7160e01b600052601260045260246000fd5b500490565b805169ffffffffffffffffffff81168114611c2b57600080fd5b600080600080600060a0868803121561579457600080fd5b61579d86615762565b94506020860151935060408601519250606086015191506157c060808701615762565b90509295509295909350565b60005b838110156157e75781810151838201526020016157cf565b838111156134295750506000910152565b6000825161580a8184602087016157cc565b9190910192915050565b60208152600082518060208401526158338160408501602087016157cc565b601f01601f19169190910160400192915050565b60008060006060848603121561585c57600080fd5b8351925060208401519150604084015190509250925092565b634e487b7160e01b600052603260045260246000fd5b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156158db5784516001600160a01b0316835293830193918301916001016158b6565b50506001600160a01b0396909616606085015250505060800152939250505056fea2646970667358221220a0fa0cb22191ca5d1b442d1f6bd2484fd66c022a69fee59bf45f61b06b1c0aa064736f6c63430008080033

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

000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff2423651000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c910000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d00000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000000006978000000000000000000000000000000000000000000000000000005af3107a4000

-----Decoded View---------------
Arg [0] : _koromaru (address): 0xD0D42005e7B3c0812b1268F0e5FAF97Ff2423651
Arg [1] : _koromaruUniV2 (address): 0xd0671e35D25d82EC6B75e3DE43975C89968D1c91
Arg [2] : _UniSwapV2FactoryAddress (address): 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f
Arg [3] : _uniswapRouter (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
Arg [4] : _apr (uint256): 690
Arg [5] : _taxToRefund (uint256): 1000
Arg [6] : _koromaruTokenDecimals (uint256): 9
Arg [7] : _koroRewardAllocation (uint256): 10000
Arg [8] : _rewardHarvestingInterval (uint256): 432000
Arg [9] : _zapKoroLimit (uint256): 100000000000000

-----Encoded View---------------
10 Constructor Arguments found :
Arg [0] : 000000000000000000000000d0d42005e7b3c0812b1268f0e5faf97ff2423651
Arg [1] : 000000000000000000000000d0671e35d25d82ec6b75e3de43975c89968d1c91
Arg [2] : 0000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f
Arg [3] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Arg [4] : 00000000000000000000000000000000000000000000000000000000000002b2
Arg [5] : 00000000000000000000000000000000000000000000000000000000000003e8
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [7] : 0000000000000000000000000000000000000000000000000000000000002710
Arg [8] : 0000000000000000000000000000000000000000000000000000000000069780
Arg [9] : 00000000000000000000000000000000000000000000000000005af3107a4000


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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