Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 235 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Emergency Withdr... | 14604816 | 1051 days ago | IN | 0 ETH | 0.00237083 | ||||
Emergency Withdr... | 14479261 | 1071 days ago | IN | 0 ETH | 0.00254752 | ||||
Deposit Koro LP ... | 14465745 | 1073 days ago | IN | 0 ETH | 0.00538848 | ||||
Emergency Withdr... | 14437669 | 1078 days ago | IN | 0 ETH | 0.00649926 | ||||
Emergency Withdr... | 14428573 | 1079 days ago | IN | 0 ETH | 0.00130707 | ||||
Emergency Withdr... | 14339650 | 1093 days ago | IN | 0 ETH | 0.00181372 | ||||
Emergency Withdr... | 14330550 | 1094 days ago | IN | 0 ETH | 0.00129121 | ||||
Emergency Withdr... | 14309054 | 1098 days ago | IN | 0 ETH | 0.00492717 | ||||
Emergency Withdr... | 14305429 | 1098 days ago | IN | 0 ETH | 0.00216868 | ||||
Emergency Withdr... | 14305429 | 1098 days ago | IN | 0 ETH | 0.00300667 | ||||
Emergency Withdr... | 14303077 | 1099 days ago | IN | 0 ETH | 0.00360611 | ||||
Harvest | 14303043 | 1099 days ago | IN | 0 ETH | 0.01089744 | ||||
Emergency Withdr... | 14299534 | 1099 days ago | IN | 0 ETH | 0.00355873 | ||||
Emergency Withdr... | 14296173 | 1100 days ago | IN | 0 ETH | 0.00717361 | ||||
Emergency Withdr... | 14295491 | 1100 days ago | IN | 0 ETH | 0.00532475 | ||||
Emergency Withdr... | 14295238 | 1100 days ago | IN | 0 ETH | 0.00310088 | ||||
Emergency Withdr... | 14293951 | 1100 days ago | IN | 0 ETH | 0.00209472 | ||||
Emergency Withdr... | 14293917 | 1100 days ago | IN | 0 ETH | 0.00327519 | ||||
Harvest | 14293283 | 1100 days ago | IN | 0 ETH | 0.00673315 | ||||
Emergency Withdr... | 14293050 | 1100 days ago | IN | 0 ETH | 0.00244111 | ||||
Emergency Withdr... | 14292031 | 1100 days ago | IN | 0 ETH | 0.00505424 | ||||
Emergency Withdr... | 14292017 | 1100 days ago | IN | 0 ETH | 0.00524574 | ||||
Harvest | 14291914 | 1100 days ago | IN | 0 ETH | 0.02130818 | ||||
Emergency Withdr... | 14290939 | 1100 days ago | IN | 0 ETH | 0.00502843 | ||||
Emergency Withdr... | 14290424 | 1100 days ago | IN | 0 ETH | 0.0034629 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
14291914 | 1100 days ago | 0.0000014 ETH | ||||
14290413 | 1100 days ago | 0.00003317 ETH | ||||
14286732 | 1101 days ago | 0.00001617 ETH | ||||
14285708 | 1101 days ago | 0.00002232 ETH | ||||
14285666 | 1101 days ago | 0.00000393 ETH | ||||
14285483 | 1101 days ago | 0.00000191 ETH | ||||
14282861 | 1102 days ago | 0.00000997 ETH | ||||
14282606 | 1102 days ago | 0.00004074 ETH | ||||
14282450 | 1102 days ago | 0.00004742 ETH | ||||
14280250 | 1102 days ago | 0.00002729 ETH | ||||
14276185 | 1103 days ago | 0.00001234 ETH | ||||
14275731 | 1103 days ago | 0.00001384 ETH | ||||
14274802 | 1103 days ago | 0.00054026 ETH | ||||
14274787 | 1103 days ago | 0.00001412 ETH | ||||
14272132 | 1103 days ago | 0.00001368 ETH | ||||
14267720 | 1104 days ago | 0.00002968 ETH | ||||
14261383 | 1105 days ago | 0.00005164 ETH | ||||
14260832 | 1105 days ago | 0.00001919 ETH | ||||
14260832 | 1105 days ago | 1 wei | ||||
14260569 | 1105 days ago | 0.00004118 ETH | ||||
14257341 | 1106 days ago | 0.00005504 ETH | ||||
14257341 | 1106 days ago | 1 wei | ||||
14255087 | 1106 days ago | 0.0000246 ETH | ||||
14255087 | 1106 days ago | 1 wei | ||||
14255040 | 1106 days ago | 0.00000801 ETH |
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
Contract Source Code (Solidity Standard Json-Input format)
// 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); } }
// 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 ); }
// 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; } }
// 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"); } } }
// 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); }
// 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; } } }
// 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; } }
// 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()); } }
// 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); } }
// 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); } } } }
// 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; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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"}]
Contract Creation Code
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
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $2,170.56 | 0.2505 | $543.79 |
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.