More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 58 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Process Token Sw... | 20352548 | 118 days ago | IN | 0 ETH | 0.00035655 | ||||
Process Token Sw... | 19793394 | 196 days ago | IN | 0 ETH | 0.00058641 | ||||
Process Token Sw... | 19793393 | 196 days ago | IN | 0 ETH | 0.00037121 | ||||
Process Token Sw... | 19548998 | 230 days ago | IN | 0 ETH | 0.00128401 | ||||
Process Token Sw... | 19545058 | 231 days ago | IN | 0 ETH | 0.00118116 | ||||
Process Token Sw... | 19522397 | 234 days ago | IN | 0 ETH | 0.0013892 | ||||
Remove Token Fro... | 19494436 | 238 days ago | IN | 0 ETH | 0.00128034 | ||||
Process Token Sw... | 19385397 | 253 days ago | IN | 0 ETH | 0.00436329 | ||||
Remove Token Fro... | 19252332 | 272 days ago | IN | 0 ETH | 0.00097869 | ||||
Remove Token Fro... | 19224053 | 276 days ago | IN | 0 ETH | 0.00076665 | ||||
Remove Token Fro... | 19217217 | 277 days ago | IN | 0 ETH | 0.00117042 | ||||
Process Token Sw... | 19202462 | 279 days ago | IN | 0 ETH | 0.02017589 | ||||
Process Token Sw... | 19194448 | 280 days ago | IN | 0 ETH | 0.0262818 | ||||
Process Token Sw... | 19191624 | 280 days ago | IN | 0 ETH | 0.06763218 | ||||
Process Token Sw... | 19185040 | 281 days ago | IN | 0 ETH | 0.00629279 | ||||
Process Token Sw... | 19185039 | 281 days ago | IN | 0 ETH | 0.00631704 | ||||
Process Token Sw... | 19174686 | 282 days ago | IN | 0 ETH | 0.02746545 | ||||
Process Token Sw... | 19174656 | 282 days ago | IN | 0 ETH | 0.02381178 | ||||
Process Token Sw... | 19174629 | 282 days ago | IN | 0 ETH | 0.03063995 | ||||
Process Token Sw... | 19174628 | 282 days ago | IN | 0 ETH | 0.02480891 | ||||
Process Token Sw... | 19174627 | 282 days ago | IN | 0 ETH | 0.02568499 | ||||
Process Token Sw... | 19174626 | 282 days ago | IN | 0 ETH | 0.01743478 | ||||
Process Token Sw... | 19174625 | 282 days ago | IN | 0 ETH | 0.02613407 | ||||
Remove Token Fro... | 19165126 | 284 days ago | IN | 0 ETH | 0.00199085 | ||||
Remove Token Fro... | 19165085 | 284 days ago | IN | 0 ETH | 0.00116156 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
LPTokenProcessorV2
Compiler Version
v0.8.4+commit.c7e474f2
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; import { KeeperCompatible } from "@chainlink/contracts/src/v0.8/KeeperCompatible.sol"; import { AccessControlEnumerable } from "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { IUniswapV2Pair } from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; import { IUniswapV2Factory } from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol"; import { IUniswapV2Router02 } from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; import { ILPTokenProcessorV2 } from "../interfaces/ILPTokenProcessorV2.sol"; import { INonfungiblePositionManager } from "../../common/interfaces/INonfungiblePositionManager.sol"; import { IPriceOracleManager } from "../../common/interfaces/IPriceOracleManager.sol"; import { ISwapRouterV3 } from "../../common/interfaces/ISwapRouterV3.sol"; contract LPTokenProcessorV2 is ILPTokenProcessorV2, KeeperCompatible, AccessControlEnumerable { using SafeERC20 for IERC20Metadata; address public constant BURN_ADDRESS = 0x000000000000000000000000000000000000dEaD; bytes32 public constant LP_ADMIN_ROLE = keccak256("LP_ADMIN_ROLE"); address public treasury; mapping(address => address) public routerByFactory; mapping(address => bool) public v2Routers; address public feeToken; address public immutable FLOKI; address public routerForFloki; IPriceOracleManager public priceOracle; uint256 private _sellDelay; mapping(address => uint256) private _lastAdded; TokenSwapInfo[] private _tokens; uint256 public constant globalBasisPoints = 10000; uint256 public constant burnBasisPoints = 2500; // 25% uint256 public constant referrerBasisPoints = 2500; // 25% uint256 public slippageBasisPoints = 300; // 3% mapping(address => uint256) public perTokenSlippage; bool public requireOraclePrice; uint24 public wethToUsdV3PoolFee = 3000; // 0.3% uint256 public feeCollectedLastBlock; uint256 public flokiBurnedLastBlock; uint256 public referrerShareLastBlock; event TokenAdded(address indexed tokenAddress); event TokenProcessed(address indexed tokenAddress); event TokenRemoved(address indexed tokenAddress); event SellDelayUpdated(uint256 indexed oldDelay, uint256 indexed newDelay); event PriceOracleUpdated(address indexed oldOracle, address indexed newOracle); event SlippageUpdated(uint256 oldSlippage, uint256 newSlippage); event SlippagePerTokenUpdated(uint256 oldSlippage, uint256 newSlippage, address token); event FeeCollected(uint256 indexed previousBlock, address indexed vault, uint256 feeAmount); event FeeTokenUpdated(address indexed oldFeeToken, address indexed newFeeToken); event ReferrerSharedPaid(uint256 indexed previousBlock, address indexed vault, address referrer, uint256 feeAmount); event FlokiBurned(uint256 indexed previousBlock, address indexed vault, uint256 feeAmount, uint256 flokiAmount); constructor( address flokiAddress, uint256 sellDelay, address mainRouter, bool isV2Router, address feeTokenAddress, address treasuryAddress, address priceOracleAddress, uint24 v3DefaultPoolFee ) { require(mainRouter != address(0), "LPTokenProcessorV2::constructor::ZERO: Router cannot be zero address."); require(feeTokenAddress != address(0), "LPTokenProcessorV2::constructor::ZERO: feeToken cannot be zero address."); require(treasuryAddress != address(0), "LPTokenProcessorV2::constructor::ZERO: Treasury cannot be zero address."); _sellDelay = sellDelay; routerForFloki = mainRouter; if (mainRouter != address(0)) { routerByFactory[IUniswapV2Router02(mainRouter).factory()] = mainRouter; v2Routers[mainRouter] = isV2Router; } FLOKI = flokiAddress; feeToken = feeTokenAddress; treasury = treasuryAddress; priceOracle = IPriceOracleManager(priceOracleAddress); wethToUsdV3PoolFee = v3DefaultPoolFee; _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); } function setFeeToken(address newFeeToken) external onlyRole(DEFAULT_ADMIN_ROLE) { require(newFeeToken != address(0), "LPTokenProcessorV2::setFeeToken::ZERO: feeToken cannot be zero address."); address oldFeeToken = feeToken; feeToken = newFeeToken; emit FeeTokenUpdated(oldFeeToken, newFeeToken); } function setSellDelay(uint256 newDelay) external onlyRole(DEFAULT_ADMIN_ROLE) { uint256 oldDelay = _sellDelay; _sellDelay = newDelay; emit SellDelayUpdated(oldDelay, newDelay); } function setPriceOracle(address newOracle) external onlyRole(DEFAULT_ADMIN_ROLE) { address oldOracle = address(priceOracle); priceOracle = IPriceOracleManager(newOracle); emit PriceOracleUpdated(oldOracle, newOracle); } function setSlippageBasisPoints(uint256 newSlippage) external onlyRole(DEFAULT_ADMIN_ROLE) { uint256 oldSlippage = slippageBasisPoints; slippageBasisPoints = newSlippage; emit SlippageUpdated(oldSlippage, newSlippage); } function setSlippagePerToken(uint256 slippage, address token) external onlyRole(DEFAULT_ADMIN_ROLE) { uint256 oldSlippage = perTokenSlippage[token]; perTokenSlippage[token] = slippage; emit SlippagePerTokenUpdated(oldSlippage, slippage, token); } function setRequireOraclePrice(bool requires) external onlyRole(DEFAULT_ADMIN_ROLE) { requireOraclePrice = requires; } function setWethToUsdV3PoolFee(uint24 newFee) external onlyRole(DEFAULT_ADMIN_ROLE) { wethToUsdV3PoolFee = newFee; } function addTokenForSwapping(TokenSwapInfo memory params) external override onlyRole(LP_ADMIN_ROLE) { // Update timestamp before checking whether token was already in the // set of locked LP tokens, because otherwise the timestamp would // not be updated on repeated calls (within the selling timeframe). uint256 initialBalance = IERC20Metadata(params.tokenAddress).balanceOf(address(this)); IERC20Metadata(params.tokenAddress).safeTransferFrom(msg.sender, address(this), params.amount); uint256 earnedAmount = IERC20Metadata(params.tokenAddress).balanceOf(address(this)) - initialBalance; _lastAdded[params.tokenAddress] = block.timestamp; _tokens.push( TokenSwapInfo({ tokenAddress: params.tokenAddress, routerFactory: params.routerFactory, isV2: params.isV2, referrer: params.referrer, vault: params.vault, amount: earnedAmount, v3PoolFee: params.v3PoolFee }) ); emit TokenAdded(params.tokenAddress); } function clearTokensFromSwapping() external onlyRole(LP_ADMIN_ROLE) { delete _tokens; } function removeTokensFromSwappingByIndexes(uint256[] memory indexes) external onlyRole(LP_ADMIN_ROLE) { for (uint256 i = 0; i < indexes.length; i++) { uint256 index = indexes[i]; address tokenAddress = _tokens[index].tokenAddress; _tokens[index] = _tokens[_tokens.length - 1]; _tokens.pop(); emit TokenRemoved(tokenAddress); } } function removeTokenFromSwapping(address tokenAddress) external onlyRole(LP_ADMIN_ROLE) { for (uint256 i = _tokens.length; i > 0; i--) { if (_tokens[i - 1].tokenAddress == tokenAddress) { _tokens[i - 1] = _tokens[_tokens.length - 1]; _tokens.pop(); break; } } } function getTokensForSwapping() external view returns (TokenSwapInfo[] memory) { return _tokens; } function addRouter(address routerAddress, bool isV2) external onlyRole(DEFAULT_ADMIN_ROLE) { require(routerAddress != address(0), "LPTokenProcessorV2::addRouter::ZERO: Router cannot be zero address."); routerByFactory[IUniswapV2Router02(routerAddress).factory()] = routerAddress; v2Routers[routerAddress] = isV2; } function getRouter(address tokenAddress) external view override returns (address) { return routerByFactory[IUniswapV2Pair(tokenAddress).factory()]; } function isV2LiquidityPoolToken(address token) external view override returns (bool) { bool success = false; bytes memory data; address tokenAddress; (success, data) = token.staticcall(abi.encodeWithSelector(IUniswapV2Pair.token0.selector)); if (!success) { return false; } assembly { tokenAddress := mload(add(data, 32)) } if (!_isContract(tokenAddress)) { return false; } (success, data) = token.staticcall(abi.encodeWithSelector(IUniswapV2Pair.token1.selector)); if (!success) { return false; } assembly { tokenAddress := mload(add(data, 32)) } if (!_isContract(tokenAddress)) { return false; } return true; } function _isContract(address externalAddress) private view returns (bool) { uint256 codeSize; assembly { codeSize := extcodesize(externalAddress) } return codeSize > 0; } function isV3LiquidityPoolToken(address tokenAddress, uint256 tokenId) external view override returns (bool) { (address token0, address token1, , ) = getV3Position(tokenAddress, tokenId); return token0 != address(0) && token1 != address(0); } function getV3Position(address tokenAddress, uint256 tokenId) public view override returns ( address, address, uint128, uint24 ) { try INonfungiblePositionManager(tokenAddress).positions(tokenId) returns ( uint96, address, address token0, address token1, uint24 fee, int24, int24, uint128 liquidity, uint256, uint256, uint128, uint128 ) { return (token0, token1, liquidity, fee); } catch { return (address(0), address(0), 0, 0); } } // Check whether any LP tokens are owned to sell. function checkUpkeep( bytes memory /* checkData */ ) external view override returns (bool upkeepNeeded, bytes memory performData) { uint256 loopLimit = _tokens.length; if (loopLimit == 0) { return (false, abi.encode("")); } for (uint256 i = 0; i < loopLimit; i++) { TokenSwapInfo memory tokenInfo = _tokens[i]; if ((_lastAdded[tokenInfo.tokenAddress] + _sellDelay) < block.timestamp) { address routerAddress = routerByFactory[tokenInfo.routerFactory]; if (routerAddress != address(0)) { // We only need one token ready for processing return (true, abi.encode("")); } } } } function performUpkeep( bytes calldata /* performData */ ) external override { uint256 tokensLength = _tokens.length; if (tokensLength == 0) { return; } for (uint256 i = 0; i < tokensLength; i++) { bool success = _processTokenSwapping(i); if (success) break; // only process one token per transaction } } function processTokenSwapping(address token) external onlyRole(LP_ADMIN_ROLE) { for (uint256 i = 0; i < _tokens.length; i++) { if (_tokens[i].tokenAddress == token) { _processTokenSwapping(i); break; } } } function processTokenSwappingByIndex(uint256 index) external onlyRole(LP_ADMIN_ROLE) { _processTokenSwapping(index); } function _processTokenSwapping(uint256 index) private returns (bool) { TokenSwapInfo memory info = _tokens[index]; address routerAddress = routerByFactory[info.routerFactory]; if (routerAddress == address(0)) return false; if ((_lastAdded[info.tokenAddress] + _sellDelay) >= block.timestamp) return false; uint256 initialFeeAmount = IERC20Metadata(feeToken).balanceOf(address(this)); if (info.isV2) { // V2 LP Tokens _swapV2TokenByFeeToken(info.tokenAddress, info.amount, routerAddress); } else { // Regular ERC20 tokens bool success = false; if (v2Routers[routerAddress]) { success = _swapTokensWithV2Router(info.tokenAddress, info.amount, feeToken, address(this), routerAddress); } else { uint24[] memory poolFees = new uint24[](2); poolFees[0] = info.v3PoolFee; poolFees[1] = wethToUsdV3PoolFee; success = _swapTokensWithV3Router(info.tokenAddress, info.amount, feeToken, poolFees, address(this), routerAddress); } require(success, "LPTokenProcessorV2::performUpkeep: Failed to swap ERC20 token by feeToken."); } uint256 newFeeAmount = IERC20Metadata(feeToken).balanceOf(address(this)); if (info.tokenAddress == feeToken) { // If the feeToken is the same as the token to be processed, there is no swap, so the balance of feeToken is not increased. // We need to manually increase the "newFeeAmount" otherwise their difference will be zero. newFeeAmount += info.amount; } uint256 feeAmount = newFeeAmount - initialFeeAmount; _processFees(info, feeAmount); _tokens[index] = _tokens[_tokens.length - 1]; _tokens.pop(); emit TokenProcessed(info.tokenAddress); return true; } /** * Unpairs the liquidity pool token and swap the unpaired tokens by feeToken. */ function _swapV2TokenByFeeToken( address tokenAddress, uint256 lpBalance, address routerAddress ) private returns (uint256) { require(routerAddress != address(0), "LPTokenProcessorV2::_swapV2TokenByFeeToken: Unsupported router."); IUniswapV2Pair lpToken = IUniswapV2Pair(tokenAddress); lpToken.approve(routerAddress, lpBalance); address token0 = lpToken.token0(); address token1 = lpToken.token1(); // liquidate and swap by feeToken IUniswapV2Router02(routerAddress).removeLiquidity(token0, token1, lpBalance, 0, 0, address(this), block.timestamp); // we can't use the amounts returned from "removeLiquidity" // because it doesn't take fees/taxes into account bool success = _swapTokensWithV2Router(token0, IERC20Metadata(token0).balanceOf(address(this)), feeToken, address(this), routerAddress); require(success, "LPTokenProcessorV2::_swapV2TokenByFeeToken: Failed to swap token0 to feeToken."); success = _swapTokensWithV2Router(token1, IERC20Metadata(token1).balanceOf(address(this)), feeToken, address(this), routerAddress); require(success, "LPTokenProcessorV2::_swapV2TokenByFeeToken: Failed to swap token1 to feeToken."); return lpBalance; } function _burnFloki(uint256 feeAmount, address vault) private returns (uint256) { // Burn FLOKI if (FLOKI != address(0)) { uint256 burnShare = (feeAmount * burnBasisPoints) / globalBasisPoints; feeAmount -= burnShare; uint256 flokiBurnedInitial = IERC20Metadata(FLOKI).balanceOf(BURN_ADDRESS); _swapTokensWithV2Router(feeToken, burnShare, FLOKI, BURN_ADDRESS, routerForFloki); uint256 flokiBurned = IERC20Metadata(FLOKI).balanceOf(BURN_ADDRESS) - flokiBurnedInitial; emit FlokiBurned(flokiBurnedLastBlock, vault, feeAmount, flokiBurned); flokiBurnedLastBlock = block.number; } return feeAmount; } function _processFees(TokenSwapInfo memory info, uint256 feeBalance) private { // Pay referrers uint256 treasuryShare = _burnFloki(feeBalance, info.vault); if (info.referrer != address(0)) { uint256 referrerShare = (feeBalance * referrerBasisPoints) / globalBasisPoints; treasuryShare -= referrerShare; IERC20Metadata(feeToken).safeTransfer(info.referrer, referrerShare); emit ReferrerSharedPaid(referrerShareLastBlock, info.vault, info.referrer, referrerShare); referrerShareLastBlock = block.number; } IERC20Metadata(feeToken).safeTransfer(treasury, treasuryShare); emit FeeCollected(feeCollectedLastBlock, info.vault, treasuryShare); feeCollectedLastBlock = block.number; } function swapTokens( address sourceToken, uint256 sourceAmount, address destinationToken, address receiver, address routerAddress, uint24[] memory poolFees ) external override returns (bool) { uint256 initialBalance = IERC20Metadata(sourceToken).balanceOf(address(this)); IERC20Metadata(sourceToken).safeTransferFrom(address(msg.sender), address(this), sourceAmount); uint256 receivedAmount = IERC20Metadata(sourceToken).balanceOf(address(this)) - initialBalance; if (v2Routers[routerAddress]) { return _swapTokensWithV2Router(sourceToken, receivedAmount, destinationToken, receiver, routerAddress); } else { return _swapTokensWithV3Router(sourceToken, receivedAmount, destinationToken, poolFees, receiver, routerAddress); } } function _swapTokensWithV2Router( address sourceToken, uint256 sourceAmount, address destinationToken, address receiver, address routerAddress ) private returns (bool) { IERC20Metadata token = IERC20Metadata(sourceToken); // if they happen to be the same, no need to swap, just transfer if (sourceToken == destinationToken) { if (receiver == address(this)) return true; token.safeTransfer(receiver, sourceAmount); return true; } IUniswapV2Router02 router = IUniswapV2Router02(routerAddress); address WETH = router.WETH(); address[] memory path; if (sourceToken == WETH || destinationToken == WETH) { path = new address[](2); path[0] = sourceToken; path[1] = destinationToken; } else { path = new address[](3); path[0] = sourceToken; path[1] = WETH; path[2] = destinationToken; } uint256 allowed = token.allowance(address(this), routerAddress); if (allowed > 0) { token.safeApprove(routerAddress, 0); } token.safeApprove(routerAddress, sourceAmount); uint256 amount = 0; if (destinationToken == feeToken) { uint256 price = _getPriceInUSDWithSlippage(sourceToken); amount = (sourceAmount * price) / 10**token.decimals(); } try router.swapExactTokensForTokensSupportingFeeOnTransferTokens(sourceAmount, amount, path, receiver, block.timestamp) {} catch ( bytes memory /* lowLevelData */ ) { return false; } return true; } function _swapTokensWithV3Router( address sourceToken, uint256 sourceAmount, address destinationToken, uint24[] memory poolFees, address receiver, address routerAddress ) private returns (bool) { IERC20Metadata token = IERC20Metadata(sourceToken); // if they happen to be the same, no need to swap, just transfer if (sourceToken == destinationToken) { if (receiver == address(this)) return true; token.safeTransfer(receiver, sourceAmount); return true; } ISwapRouterV3 router = ISwapRouterV3(routerAddress); address WETH = router.WETH9(); bytes memory path; if (sourceToken == WETH || destinationToken == WETH) { path = abi.encodePacked(sourceToken, poolFees[0], destinationToken); } else { path = abi.encodePacked(sourceToken, poolFees[0], WETH, poolFees[1], destinationToken); } uint256 allowed = token.allowance(address(this), routerAddress); if (allowed > 0) { token.safeApprove(routerAddress, 0); } token.safeApprove(routerAddress, sourceAmount); uint256 amount = 0; if (destinationToken == feeToken) { uint256 price = _getPriceInUSDWithSlippage(sourceToken); amount = (sourceAmount * price) / 10**token.decimals(); } ISwapRouterV3.ExactInputParams memory params = ISwapRouterV3.ExactInputParams({ path: path, recipient: receiver, amountIn: sourceAmount, amountOutMinimum: amount }); try router.exactInput(params) returns (uint256 amountOut) {} catch ( bytes memory /* lowLevelData */ ) { return false; } return true; } function _getPriceInUSDWithSlippage(address token) private returns (uint256) { if (address(priceOracle) == address(0)) { return 0; } priceOracle.fetchPriceInUSD(token); // the USD price in the same decimals as the feeToken token uint256 price = priceOracle.getPriceInUSD(token, IERC20Metadata(feeToken).decimals()); require(price > 0 || !requireOraclePrice, "LPTokenProcessorV2::_getPriceWithSlippage: Price is zero."); uint256 slippage = perTokenSlippage[token]; if (slippage == 0) { slippage = slippageBasisPoints; } return price - ((price * slippage) / globalBasisPoints); } function adminWithdraw( address tokenAddress, uint256 amount, address destination ) external onlyRole(DEFAULT_ADMIN_ROLE) { if (tokenAddress == address(0)) { // We specifically ignore this return value. (bool success, ) = payable(destination).call{ value: amount }(""); require(success, "Failed to withdraw ETH"); } else { IERC20Metadata(tokenAddress).safeTransfer(destination, amount); } } receive() external payable {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract KeeperBase { error OnlySimulatedBackend(); /** * @notice method that allows it to be simulated via eth_call by checking that * the sender is the zero address. */ function preventExecution() internal view { if (tx.origin != address(0)) { revert OnlySimulatedBackend(); } } /** * @notice modifier that allows it to be simulated via eth_call by checking * that the sender is the zero address. */ modifier cannotExecute() { preventExecution(); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./KeeperBase.sol"; import "./interfaces/KeeperCompatibleInterface.sol"; abstract contract KeeperCompatible is KeeperBase, KeeperCompatibleInterface {}
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface KeeperCompatibleInterface { /** * @notice method that is simulated by the keepers to see if any work actually * needs to be performed. This method does does not actually need to be * executable, and since it is only ever simulated it can consume lots of gas. * @dev To ensure that it is never called, you may want to add the * cannotExecute modifier from KeeperBase to your implementation of this * method. * @param checkData specified in the upkeep registration so it is always the * same for a registered upkeep. This can easily be broken down into specific * arguments using `abi.decode`, so multiple upkeeps can be registered on the * same contract and easily differentiated by the contract. * @return upkeepNeeded boolean to indicate whether the keeper should call * performUpkeep or not. * @return performData bytes that the keeper should call performUpkeep with, if * upkeep is needed. If you would like to encode data to decode later, try * `abi.encode`. */ function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData); /** * @notice method that is actually executed by the keepers, via the registry. * The data returned by the checkUpkeep simulation will be passed into * this method to actually be executed. * @dev The input to this method should not be trusted, and the caller of the * method should not even be restricted to any single registry. Anyone should * be able call it, and the input should be validated, there is no guarantee * that the data passed in is the performData returned from checkUpkeep. This * could happen due to malicious keepers, racing keepers, or simply a state * change while the performUpkeep transaction is waiting for confirmation. * Always validate the data passed in. * @param performData is the data which was passed back from the checkData * simulation. If it is encoded, it can easily be decoded into other types by * calling `abi.decode`. This data should not be trusted, and should be * validated against the contract's current state. */ function performUpkeep(bytes calldata performData) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(uint160(account), 20), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControlEnumerable.sol"; import "./AccessControl.sol"; import "../utils/structs/EnumerableSet.sol"; /** * @dev Extension of {AccessControl} that allows enumerating the members of each role. */ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl { using EnumerableSet for EnumerableSet.AddressSet; mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) { return _roleMembers[role].at(index); } /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) { return _roleMembers[role].length(); } /** * @dev Overload {_grantRole} to track enumerable memberships */ function _grantRole(bytes32 role, address account) internal virtual override { super._grantRole(role, account); _roleMembers[role].add(account); } /** * @dev Overload {_revokeRole} to track enumerable memberships */ function _revokeRole(bytes32 role, address account) internal virtual override { super._revokeRole(role, account); _roleMembers[role].remove(account); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; /** * @dev External interface of AccessControlEnumerable declared to support ERC165 detection. */ interface IAccessControlEnumerable is IAccessControl { /** * @dev Returns one of the accounts that have `role`. `index` must be a * value between 0 and {getRoleMemberCount}, non-inclusive. * * Role bearers are not sorted in any particular way, and their ordering may * change at any point. * * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure * you perform all queries on the same block. See the following * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] * for more information. */ function getRoleMember(bytes32 role, uint256 index) external view returns (address); /** * @dev Returns the number of accounts that have `role`. Can be used * together with {getRoleMember} to enumerate all bearers of a role. */ function getRoleMemberCount(bytes32 role) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.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)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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 (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.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. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. * ==== */ 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; /// @solidity memory-safe-assembly 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; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
pragma solidity >=0.5.0; interface IUniswapV2Factory { event PairCreated(address indexed token0, address indexed token1, address pair, uint); function feeTo() external view returns (address); function feeToSetter() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint) external view returns (address pair); function allPairsLength() external view returns (uint); function createPair(address tokenA, address tokenB) external returns (address pair); function setFeeTo(address) external; function setFeeToSetter(address) external; }
pragma solidity >=0.5.0; interface IUniswapV2Pair { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); function kLast() external view returns (uint); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function skim(address to) external; function sync() external; function initialize(address, address) external; }
pragma solidity >=0.6.2; interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); }
pragma solidity >=0.6.2; import './IUniswapV2Router01.sol'; interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.4; pragma abicoder v2; import { IERC721Enumerable } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol"; /// @title Non-fungible token for positions /// @notice Wraps Uniswap V3 positions in a non-fungible token interface which allows for them to be transferred /// and authorized. interface INonfungiblePositionManager is IERC721Enumerable { /// @notice Returns the position information associated with a given token ID. /// @dev Throws if the token ID is not valid. /// @param tokenId The ID of the token that represents the position /// @return nonce The nonce for permits /// @return operator The address that is approved for spending /// @return token0 The address of the token0 for a specific pool /// @return token1 The address of the token1 for a specific pool /// @return fee The fee associated with the pool /// @return tickLower The lower end of the tick range for the position /// @return tickUpper The higher end of the tick range for the position /// @return liquidity The liquidity of the position /// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last action on the individual position /// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last action on the individual position /// @return tokensOwed0 The uncollected amount of token0 owed to the position as of the last computation /// @return tokensOwed1 The uncollected amount of token1 owed to the position as of the last computation function positions(uint256 tokenId) external view returns ( uint96 nonce, address operator, address token0, address token1, uint24 fee, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1 ); struct MintParams { address token0; address token1; uint24 fee; int24 tickLower; int24 tickUpper; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; address recipient; uint256 deadline; } /// @notice Creates a new position wrapped in a NFT /// @dev Call this when the pool does exist and is initialized. Note that if the pool is created but not initialized /// a method does not exist, i.e. the pool is assumed to be initialized. /// @param params The params necessary to mint a position, encoded as `MintParams` in calldata /// @return tokenId The ID of the token that represents the minted position /// @return liquidity The amount of liquidity for this position /// @return amount0 The amount of token0 /// @return amount1 The amount of token1 function mint(MintParams calldata params) external payable returns ( uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1 ); struct IncreaseLiquidityParams { uint256 tokenId; uint256 amount0Desired; uint256 amount1Desired; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } /// @notice Increases the amount of liquidity in a position, with tokens paid by the `msg.sender` /// @param params tokenId The ID of the token for which liquidity is being increased, /// amount0Desired The desired amount of token0 to be spent, /// amount1Desired The desired amount of token1 to be spent, /// amount0Min The minimum amount of token0 to spend, which serves as a slippage check, /// amount1Min The minimum amount of token1 to spend, which serves as a slippage check, /// deadline The time by which the transaction must be included to effect the change /// @return liquidity The new liquidity amount as a result of the increase /// @return amount0 The amount of token0 to acheive resulting liquidity /// @return amount1 The amount of token1 to acheive resulting liquidity function increaseLiquidity(IncreaseLiquidityParams calldata params) external payable returns ( uint128 liquidity, uint256 amount0, uint256 amount1 ); struct DecreaseLiquidityParams { uint256 tokenId; uint128 liquidity; uint256 amount0Min; uint256 amount1Min; uint256 deadline; } /// @notice Decreases the amount of liquidity in a position and accounts it to the position /// @param params tokenId The ID of the token for which liquidity is being decreased, /// amount The amount by which liquidity will be decreased, /// amount0Min The minimum amount of token0 that should be accounted for the burned liquidity, /// amount1Min The minimum amount of token1 that should be accounted for the burned liquidity, /// deadline The time by which the transaction must be included to effect the change /// @return amount0 The amount of token0 accounted to the position's tokens owed /// @return amount1 The amount of token1 accounted to the position's tokens owed function decreaseLiquidity(DecreaseLiquidityParams calldata params) external payable returns (uint256 amount0, uint256 amount1); struct CollectParams { uint256 tokenId; address recipient; uint128 amount0Max; uint128 amount1Max; } /// @notice Collects up to a maximum amount of fees owed to a specific position to the recipient /// @param params tokenId The ID of the NFT for which tokens are being collected, /// recipient The account that should receive the tokens, /// amount0Max The maximum amount of token0 to collect, /// amount1Max The maximum amount of token1 to collect /// @return amount0 The amount of fees collected in token0 /// @return amount1 The amount of fees collected in token1 function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1); /// @notice Burns a token ID, which deletes it from the NFT contract. The token must have 0 liquidity and all tokens /// must be collected first. /// @param tokenId The ID of the token that is being burned function burn(uint256 tokenId) external payable; function factory() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; interface IPriceOracleManager { /** * Fetches the USD price for a token if required */ function fetchPriceInUSD(address sourceToken) external; /** * Returns the price of the token in USD, normalized to the expected decimals param. */ function getPriceInUSD(address token, uint256 expectedDecimals) external view returns (uint256 price); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; interface ISwapRouterV3 { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 amountIn; uint256 amountOutMinimum; } function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); function WETH9() external pure returns (address); function factory() external pure returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.4; interface ILPTokenProcessorV2 { struct TokenSwapInfo { address tokenAddress; address routerFactory; bool isV2; address referrer; address vault; uint256 amount; uint24 v3PoolFee; } function addTokenForSwapping(TokenSwapInfo memory params) external; function getRouter(address lpTokenAddress) external view returns (address); function getV3Position(address tokenAddress, uint256 tokenId) external view returns ( address, address, uint128, uint24 ); function isV2LiquidityPoolToken(address tokenAddress) external view returns (bool); function isV3LiquidityPoolToken(address tokenAddress, uint256 tokenId) external view returns (bool); function swapTokens( address sourceToken, uint256 sourceAmount, address destinationToken, address receiver, address routerAddress, uint24[] memory poolFees ) external returns (bool); }
{ "evmVersion": "istanbul", "libraries": {}, "metadata": { "bytecodeHash": "none", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 800 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"flokiAddress","type":"address"},{"internalType":"uint256","name":"sellDelay","type":"uint256"},{"internalType":"address","name":"mainRouter","type":"address"},{"internalType":"bool","name":"isV2Router","type":"bool"},{"internalType":"address","name":"feeTokenAddress","type":"address"},{"internalType":"address","name":"treasuryAddress","type":"address"},{"internalType":"address","name":"priceOracleAddress","type":"address"},{"internalType":"uint24","name":"v3DefaultPoolFee","type":"uint24"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"previousBlock","type":"uint256"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"FeeCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldFeeToken","type":"address"},{"indexed":true,"internalType":"address","name":"newFeeToken","type":"address"}],"name":"FeeTokenUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"previousBlock","type":"uint256"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"flokiAmount","type":"uint256"}],"name":"FlokiBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOracle","type":"address"},{"indexed":true,"internalType":"address","name":"newOracle","type":"address"}],"name":"PriceOracleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"previousBlock","type":"uint256"},{"indexed":true,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"ReferrerSharedPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"oldDelay","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"newDelay","type":"uint256"}],"name":"SellDelayUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldSlippage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSlippage","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"SlippagePerTokenUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldSlippage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSlippage","type":"uint256"}],"name":"SlippageUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"}],"name":"TokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"}],"name":"TokenProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"}],"name":"TokenRemoved","type":"event"},{"inputs":[],"name":"BURN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FLOKI","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LP_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"routerAddress","type":"address"},{"internalType":"bool","name":"isV2","type":"bool"}],"name":"addRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"routerFactory","type":"address"},{"internalType":"bool","name":"isV2","type":"bool"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint24","name":"v3PoolFee","type":"uint24"}],"internalType":"struct ILPTokenProcessorV2.TokenSwapInfo","name":"params","type":"tuple"}],"name":"addTokenForSwapping","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"destination","type":"address"}],"name":"adminWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burnBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"clearTokensFromSwapping","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeCollectedLastBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flokiBurnedLastBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"getRouter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokensForSwapping","outputs":[{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"routerFactory","type":"address"},{"internalType":"bool","name":"isV2","type":"bool"},{"internalType":"address","name":"referrer","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint24","name":"v3PoolFee","type":"uint24"}],"internalType":"struct ILPTokenProcessorV2.TokenSwapInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getV3Position","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"isV2LiquidityPoolToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isV3LiquidityPoolToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"perTokenSlippage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"performUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"priceOracle","outputs":[{"internalType":"contract IPriceOracleManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"processTokenSwapping","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"processTokenSwappingByIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"referrerBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referrerShareLastBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"removeTokenFromSwapping","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"indexes","type":"uint256[]"}],"name":"removeTokensFromSwappingByIndexes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requireOraclePrice","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"routerByFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"routerForFloki","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeToken","type":"address"}],"name":"setFeeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOracle","type":"address"}],"name":"setPriceOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"requires","type":"bool"}],"name":"setRequireOraclePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newDelay","type":"uint256"}],"name":"setSellDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newSlippage","type":"uint256"}],"name":"setSlippageBasisPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"slippage","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"name":"setSlippagePerToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"newFee","type":"uint24"}],"name":"setWethToUsdV3PoolFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slippageBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sourceToken","type":"address"},{"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"internalType":"address","name":"destinationToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"routerAddress","type":"address"},{"internalType":"uint24[]","name":"poolFees","type":"uint24[]"}],"name":"swapTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"v2Routers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wethToUsdV3PoolFee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a060405261012c600b55600d805463ffffff001916620bb8001790553480156200002957600080fd5b50604051620055d2380380620055d28339810160408190526200004c91620004c9565b6001600160a01b038616620000cb5760405162461bcd60e51b81526020600482015260456024820152600080516020620055b283398151915260448201527f3a5a45524f3a20526f757465722063616e6e6f74206265207a65726f206164646064820152643932b9b99760d91b608482015260a4015b60405180910390fd5b6001600160a01b038416620001485760405162461bcd60e51b81526020600482015260476024820152600080516020620055b283398151915260448201527f3a5a45524f3a20666565546f6b656e2063616e6e6f74206265207a65726f206160648201526632323932b9b99760c91b608482015260a401620000c2565b6001600160a01b038316620001c55760405162461bcd60e51b81526020600482015260476024820152600080516020620055b283398151915260448201527f3a5a45524f3a2054726561737572792063616e6e6f74206265207a65726f206160648201526632323932b9b99760c91b608482015260a401620000c2565b6008879055600680546001600160a01b0319166001600160a01b03881690811790915515620002b6578560036000886001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b1580156200022d57600080fd5b505afa15801562000242573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002689190620004ac565b6001600160a01b0390811682526020808301939093526040918201600090812080546001600160a01b031916958316959095179094558916835260049091529020805460ff19168615151790555b606088901b6001600160601b031916608052600580546001600160a01b03199081166001600160a01b038781169190911790925560028054821686841617905560078054909116918416919091179055600d805463ffffff00191661010062ffffff8416021790556200032b60003362000339565b505050505050505062000576565b6200035082826200037c60201b6200209f1760201c565b6000828152600160209081526040909120620003779183906200213d6200041d821b17901c565b505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1662000419576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620003d83390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b600062000434836001600160a01b0384166200043d565b90505b92915050565b6000818152600183016020526040812054620004865750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000437565b50600062000437565b80516001600160a01b0381168114620004a757600080fd5b919050565b600060208284031215620004be578081fd5b62000434826200048f565b600080600080600080600080610100898b031215620004e6578384fd5b620004f1896200048f565b9750602089015196506200050860408a016200048f565b9550606089015180151581146200051d578485fd5b94506200052d60808a016200048f565b93506200053d60a08a016200048f565b92506200054d60c08a016200048f565b915060e089015162ffffff8116811462000565578182fd5b809150509295985092959890939650565b60805160601c615001620005b160003960008181610557015281816140e10152818161415a015281816141f1015261424001526150016000f3fe6080604052600436106103385760003560e01c80636e04ff0d116101b0578063c60bb02e116100ec578063e23bfa5a11610095578063f1787dbe1161006f578063f1787dbe146109d9578063f426754214610a0f578063f79bcad014610a2f578063fccc281314610a4457600080fd5b8063e23bfa5a1461098d578063e39e927b146109a3578063ec49e921146109b957600080fd5b8063cd8afc00116100c6578063cd8afc00146108e6578063d547741f1461094d578063dee633631461096d57600080fd5b8063c60bb02e14610886578063ca15c873146108a6578063cab35423146108c657600080fd5b806391d14854116101595780639a436c9b116101335780639a436c9b146105cf5780639c76015a1461083b578063a217fddf1461085b578063c17036461461087057600080fd5b806391d14854146107b7578063951cfc82146107fb5780639654a3091461081b57600080fd5b80638369166d1161018a5780638369166d146107575780638b944542146107775780639010d07c1461079757600080fd5b80636e04ff0d146106db5780636e4e294f14610709578063809544741461073d57600080fd5b80632f9f8c131161027f57806352ef1da91161022857806356e1887d1161020257806356e1887d1461065b57806361d027b31461067b578063647846a51461069b5780636b27a811146106bb57600080fd5b806352ef1da914610605578063530e784f1461061b578063539c07c71461063b57600080fd5b80634585e33b116102595780634585e33b146105af578063470cc5f2146105cf578063495cdcde146105e557600080fd5b80632f9f8c131461054557806336568abe1461057957806344c6d80b1461059957600080fd5b806315cce224116102e1578063248a9ca3116102bb578063248a9ca3146104bd5780632630c12f146104ed5780632f2ff15d1461052557600080fd5b806315cce2241461045b5780631c3abd651461047b57806323a2e1a81461049b57600080fd5b806305f91e6f1161031257806305f91e6f146103d05780630aed36d01461040057806311eb1b861461042057600080fd5b806301ffc9a71461034457806302013695146103795780630400828c146103ae57600080fd5b3661033f57005b600080fd5b34801561035057600080fd5b5061036461035f36600461480b565b610a5a565b60405190151581526020015b60405180910390f35b34801561038557600080fd5b50600d5461039a90610100900462ffffff1681565b60405162ffffff9091168152602001610370565b3480156103ba57600080fd5b506103ce6103c93660046147ae565b610a85565b005b3480156103dc57600080fd5b506103646103eb366004614511565b60046020526000908152604090205460ff1681565b34801561040c57600080fd5b506103ce61041b366004614549565b610ad6565b34801561042c57600080fd5b5061044d61043b366004614511565b600c6020526000908152604090205481565b604051908152602001610370565b34801561046757600080fd5b506103ce610476366004614511565b610c3a565b34801561048757600080fd5b50610364610496366004614581565b610d3a565b3480156104a757600080fd5b506104b0610d79565b6040516103709190614bfd565b3480156104c957600080fd5b5061044d6104d83660046147ae565b60009081526020819052604090206001015490565b3480156104f957600080fd5b5060075461050d906001600160a01b031681565b6040516001600160a01b039091168152602001610370565b34801561053157600080fd5b506103ce6105403660046147c6565b610e35565b34801561055157600080fd5b5061050d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561058557600080fd5b506103ce6105943660046147c6565b610e5f565b3480156105a557600080fd5b5061044d61271081565b3480156105bb57600080fd5b506103ce6105ca366004614833565b610eeb565b3480156105db57600080fd5b5061044d6109c481565b3480156105f157600080fd5b50610364610600366004614511565b610f35565b34801561061157600080fd5b5061044d600b5481565b34801561062757600080fd5b506103ce610636366004614511565b6110a0565b34801561064757600080fd5b5060065461050d906001600160a01b031681565b34801561066757600080fd5b506103ce6106763660046145ac565b6110fe565b34801561068757600080fd5b5060025461050d906001600160a01b031681565b3480156106a757600080fd5b5060055461050d906001600160a01b031681565b3480156106c757600080fd5b506103646106d63660046145ed565b6111d4565b3480156106e757600080fd5b506106fb6106f63660046148a0565b61133f565b604051610370929190614c98565b34801561071557600080fd5b5061044d7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c013681781565b34801561074957600080fd5b50600d546103649060ff1681565b34801561076357600080fd5b5061050d610772366004614511565b6114c5565b34801561078357600080fd5b506103ce610792366004614511565b61155f565b3480156107a357600080fd5b5061050d6107b23660046147ea565b6117a6565b3480156107c357600080fd5b506103646107d23660046147c6565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561080757600080fd5b506103ce6108163660046149dd565b6117c5565b34801561082757600080fd5b506103ce61083636600461492d565b6117f1565b34801561084757600080fd5b506103ce6108563660046147c6565b611b4c565b34801561086757600080fd5b5061044d600081565b34801561087c57600080fd5b5061044d60105481565b34801561089257600080fd5b506103ce6108a1366004614776565b611bbd565b3480156108b257600080fd5b5061044d6108c13660046147ae565b611bdc565b3480156108d257600080fd5b506103ce6108e13660046147ae565b611bf3565b3480156108f257600080fd5b50610906610901366004614581565b611c26565b604080516001600160a01b0395861681529490931660208501526fffffffffffffffffffffffffffffffff9091169183019190915262ffffff166060820152608001610370565b34801561095957600080fd5b506103ce6109683660046147c6565b611cdb565b34801561097957600080fd5b506103ce6109883660046146e3565b611d00565b34801561099957600080fd5b5061044d600e5481565b3480156109af57600080fd5b5061044d600f5481565b3480156109c557600080fd5b506103ce6109d43660046147ae565b611f84565b3480156109e557600080fd5b5061050d6109f4366004614511565b6003602052600090815260409020546001600160a01b031681565b348015610a1b57600080fd5b506103ce610a2a366004614511565b611fc9565b348015610a3b57600080fd5b506103ce612066565b348015610a5057600080fd5b5061050d61dead81565b60006001600160e01b03198216635a05180f60e01b1480610a7f5750610a7f82612152565b92915050565b6000610a9081612187565b600b80549083905560408051828152602081018590527f07af09e2b23ebab5dd29fa2271d6ca4795031f308caf26ca605f4a719ffeed61910160405180910390a1505050565b6000610ae181612187565b6001600160a01b038316610b6e5760405162461bcd60e51b815260206004820152604360248201527f4c50546f6b656e50726f636573736f7256323a3a616464526f757465723a3a5a60448201527f45524f3a20526f757465722063616e6e6f74206265207a65726f20616464726560648201526239b99760e91b608482015260a4015b60405180910390fd5b8260036000856001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b158015610bac57600080fd5b505afa158015610bc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be4919061452d565b6001600160a01b0390811682526020808301939093526040918201600090812080546001600160a01b031916958316959095179094559590951682526004905292909220805460ff191691151591909117905550565b6000610c4581612187565b6001600160a01b038216610ce75760405162461bcd60e51b815260206004820152604760248201527f4c50546f6b656e50726f636573736f7256323a3a736574466565546f6b656e3a60448201527f3a5a45524f3a20666565546f6b656e2063616e6e6f74206265207a65726f206160648201527f6464726573732e00000000000000000000000000000000000000000000000000608482015260a401610b65565b600580546001600160a01b038481166001600160a01b0319831681179093556040519116919082907f91a03e1d689caf891fe531c01e290f7b718f9c6a3af6726d6d837d2b7bd82e6790600090a3505050565b6000806000610d498585611c26565b509193509150506001600160a01b03821615801590610d7057506001600160a01b03811615155b95945050505050565b6060600a805480602002602001604051908101604052809291908181526020016000905b82821015610e2c5760008481526020908190206040805160e0810182526006860290920180546001600160a01b03908116845260018083015480831686880152600160a01b900460ff161515938501939093526002820154811660608501526003820154166080840152600481015460a08401526005015462ffffff1660c08301529083529092019101610d9d565b50505050905090565b600082815260208190526040902060010154610e5081612187565b610e5a8383612191565b505050565b6001600160a01b0381163314610edd5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610b65565b610ee782826121b3565b5050565b600a5480610ef857505050565b60005b81811015610f2f576000610f0e826121d5565b90508015610f1c5750610f2f565b5080610f2781614f79565b915050610efb565b50505050565b60408051600481526024810182526020810180516001600160e01b0316630dfe168160e01b1790529051600091829160609183916001600160a01b03871691610f7d91614b60565b600060405180830381855afa9150503d8060008114610fb8576040519150601f19603f3d011682016040523d82523d6000602084013e610fbd565b606091505b50909350915082610fd357506000949350505050565b506020810151803b610fea57506000949350505050565b60408051600481526024810182526020810180516001600160e01b031663d21220a760e01b17905290516001600160a01b0387169161102891614b60565b600060405180830381855afa9150503d8060008114611063576040519150601f19603f3d011682016040523d82523d6000602084013e611068565b606091505b5090935091508261107e57506000949350505050565b506020810151803b61109557506000949350505050565b506001949350505050565b60006110ab81612187565b600780546001600160a01b038481166001600160a01b0319831681179093556040519116919082907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a3505050565b600061110981612187565b6001600160a01b0384166111c0576000826001600160a01b03168460405160006040518083038185875af1925050503d8060008114611164576040519150601f19603f3d011682016040523d82523d6000602084013e611169565b606091505b50509050806111ba5760405162461bcd60e51b815260206004820152601660248201527f4661696c656420746f20776974686472617720455448000000000000000000006044820152606401610b65565b50610f2f565b610f2f6001600160a01b03851683856127ac565b6040516370a0823160e01b815230600482015260009081906001600160a01b038916906370a082319060240160206040518083038186803b15801561121857600080fd5b505afa15801561122c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125091906149f9565b90506112676001600160a01b03891633308a61280f565b6040516370a0823160e01b815230600482015260009082906001600160a01b038b16906370a082319060240160206040518083038186803b1580156112ab57600080fd5b505afa1580156112bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e391906149f9565b6112ed9190614f1f565b6001600160a01b03861660009081526004602052604090205490915060ff16156113275761131e8982898989612847565b92505050611335565b61131e898289878a8a612cfd565b9695505050505050565b600a546000906060908061137b576040805160208082015260009181018290526060016040516020818303038152906040529250925050915091565b60005b818110156114be576000600a82815481106113a957634e487b7160e01b600052603260045260246000fd5b600091825260208083206040805160e081018252600690940290910180546001600160a01b0390811680865260018301548083168787015260ff600160a01b9091041615158685015260028301548216606087015260038301549091166080860152600482015460a086015260059091015462ffffff1660c0850152600854908552600990925290922054909250429161144291614dda565b10156114ab576020808201516001600160a01b03908116600090815260039092526040909120541680156114a957600160405160200161148d90602080825260009082015260400190565b6040516020818303038152906040529550955050505050915091565b505b50806114b681614f79565b91505061137e565b5050915091565b600060036000836001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b15801561150457600080fd5b505afa158015611518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153c919061452d565b6001600160a01b0390811682526020820192909252604001600020541692915050565b7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c013681761158981612187565b600a545b8015610e5a576001600160a01b038316600a6115aa600184614f1f565b815481106115c857634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201546001600160a01b0316141561179457600a80546115f890600190614f1f565b8154811061161657634e487b7160e01b600052603260045260246000fd5b9060005260206000209060060201600a6001836116339190614f1f565b8154811061165157634e487b7160e01b600052603260045260246000fd5b60009182526020909120825460069092020180546001600160a01b03199081166001600160a01b039384161782556001808501805491840180548085169387169384178255915460ff600160a01b91829004161515026001600160a81b0319909216909217179055600280850154908301805483169185169190911790556003808501549083018054909216931692909217909155600480830154908201556005918201549101805462ffffff191662ffffff909216919091179055600a80548061172c57634e487b7160e01b600052603160045260246000fd5b60008281526020812060066000199093019283020180546001600160a01b031990811682556001820180546001600160a81b03191690556002820180548216905560038201805490911690556004810191909155600501805462ffffff191690559055505050565b8061179e81614f62565b91505061158d565b60008281526001602052604081206117be90836131da565b9392505050565b60006117d081612187565b50600d805462ffffff9092166101000263ffffff0019909216919091179055565b7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c013681761181b81612187565b81516040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561185e57600080fd5b505afa158015611872573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189691906149f9565b60a084015184519192506118b7916001600160a01b0316903390309061280f565b82516040516370a0823160e01b815230600482015260009183916001600160a01b03909116906370a082319060240160206040518083038186803b1580156118fe57600080fd5b505afa158015611912573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193691906149f9565b6119409190614f1f565b84516001600160a01b039081166000908152600960209081526040808320429055805160e081018252895185168152828a01518516928101928352818a015115158183019081526060808c015187169083019081526080808d0151881690840190815260a0840189815260c0808f015162ffffff908116918701918252600a8054600181018255908b5296517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8600690980297880180546001600160a01b0319908116928e1692909217905598517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a9880180549751918d166001600160a81b031990981697909717600160a01b911515919091021790955592517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2aa860180548916918b1691909117905590517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2ab850180549097169089161790955593517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2ac83015592517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2ad909101805462ffffff1916919093161790915587519051939450909116917f784c8f4dbf0ffedd6e72c76501c545a70f8b203b30a26ce542bf92ba87c248a49190a250505050565b6000611b5781612187565b6001600160a01b0382166000818152600c602090815260409182902080549087905582518181529182018790528183019390935290517fdbf456df41211767ed3f69868f89dce56871ab4769bcc87b0ffdebef7bb74abf9181900360600190a150505050565b6000611bc881612187565b50600d805460ff1916911515919091179055565b6000818152600160205260408120610a7f906131e6565b7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c0136817611c1d81612187565b610e5a826121d5565b600080600080856001600160a01b03166399fbab88866040518263ffffffff1660e01b8152600401611c5a91815260200190565b6101806040518083038186803b158015611c7357600080fd5b505afa925050508015611ca3575060408051601f3d908101601f19168201909252611ca091810190614a55565b60015b611cb857506000925082915081905080611cd2565b50979d50959b50909950929750611cd29650505050505050565b92959194509250565b600082815260208190526040902060010154611cf681612187565b610e5a83836121b3565b7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c0136817611d2a81612187565b60005b8251811015610e5a576000838281518110611d5857634e487b7160e01b600052603260045260246000fd5b602002602001015190506000600a8281548110611d8557634e487b7160e01b600052603260045260246000fd5b6000918252602090912060069091020154600a80546001600160a01b03909216925090611db490600190614f1f565b81548110611dd257634e487b7160e01b600052603260045260246000fd5b9060005260206000209060060201600a8381548110611e0157634e487b7160e01b600052603260045260246000fd5b60009182526020909120825460069092020180546001600160a01b03199081166001600160a01b039384161782556001808501805491840180548085169387169384178255915460ff600160a01b91829004161515026001600160a81b0319909216909217179055600280850154908301805483169185169190911790556003808501549083018054909216931692909217909155600480830154908201556005918201549101805462ffffff191662ffffff909216919091179055600a805480611edc57634e487b7160e01b600052603160045260246000fd5b60008281526020812060066000199093019283020180546001600160a01b031990811682556001820180546001600160a81b031916905560028201805482169055600382018054909116905560048101829055600501805462ffffff1916905591556040516001600160a01b038316917f4c910b69fe65a61f7531b9c5042b2329ca7179c77290aa7e2eb3afa3c8511fd391a250508080611f7c90614f79565b915050611d2d565b6000611f8f81612187565b6008805490839055604051839082907f7ff6561fd143a7a81e57b057370065fec411691ad4ea760fcdd900587f35ba2990600090a3505050565b7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c0136817611ff381612187565b60005b600a54811015610e5a57826001600160a01b0316600a828154811061202b57634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201546001600160a01b0316141561205457610f2f816121d5565b8061205e81614f79565b915050611ff6565b7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c013681761209081612187565b61209c600a6000614431565b50565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610ee7576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556120f93390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006117be836001600160a01b0384166131f0565b60006001600160e01b03198216637965db0b60e01b1480610a7f57506301ffc9a760e01b6001600160e01b0319831614610a7f565b61209c813361323f565b61219b828261209f565b6000828152600160205260409020610e5a908261213d565b6121bd82826132bd565b6000828152600160205260409020610e5a908261333c565b600080600a83815481106121f957634e487b7160e01b600052603260045260246000fd5b600091825260208083206040805160e08101825260069490940290910180546001600160a01b0390811685526001820154808216868601819052600160a01b90910460ff1615158685015260028301548216606087015260038084015483166080880152600484015460a088015260059093015462ffffff1660c087015286529252909220549092501680612292575060009392505050565b60085482516001600160a01b031660009081526009602052604090205442916122ba91614dda565b106122c9575060009392505050565b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561230d57600080fd5b505afa158015612321573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061234591906149f9565b905082604001511561236a5761236483600001518460a0015184613351565b5061250f565b6001600160a01b03821660009081526004602052604081205460ff16156123b257835160a08501516005546123ab9291906001600160a01b03163087612847565b9050612474565b6040805160028082526060820183526000926020830190803683370190505090508460c00151816000815181106123f957634e487b7160e01b600052603260045260246000fd5b62ffffff9283166020918202929092010152600d548251610100909104909116908290600190811061243b57634e487b7160e01b600052603260045260246000fd5b62ffffff90921660209283029190910190910152845160a08601516005546124709291906001600160a01b0316843089612cfd565b9150505b8061250d5760405162461bcd60e51b815260206004820152604a60248201527f4c50546f6b656e50726f636573736f7256323a3a706572666f726d55706b656560448201527f703a204661696c656420746f207377617020455243323020746f6b656e20627960648201527f20666565546f6b656e2e00000000000000000000000000000000000000000000608482015260a401610b65565b505b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561255357600080fd5b505afa158015612567573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258b91906149f9565b60055485519192506001600160a01b03918216911614156125b85760a08401516125b59082614dda565b90505b60006125c48383614f1f565b90506125d085826137ee565b600a80546125e090600190614f1f565b815481106125fe57634e487b7160e01b600052603260045260246000fd5b9060005260206000209060060201600a888154811061262d57634e487b7160e01b600052603260045260246000fd5b60009182526020909120825460069092020180546001600160a01b03199081166001600160a01b039384161782556001808501805491840180548085169387169384178255915460ff600160a01b91829004161515026001600160a81b0319909216909217179055600280850154908301805483169185169190911790556003808501549083018054909216931692909217909155600480830154908201556005918201549101805462ffffff191662ffffff909216919091179055600a80548061270857634e487b7160e01b600052603160045260246000fd5b60008281526020812060066000199093019283020180546001600160a01b031990811682556001820180546001600160a81b031916905560028201805482169055600382018054909116905560048101829055600501805462ffffff19169055915585516040516001600160a01b0391909116917fd5512cb11a9597e816b26c674dbb6372fbb9c1bb69e088a8d0841b493db03fa491a25060019695505050505050565b6040516001600160a01b038316602482015260448101829052610e5a90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613932565b6040516001600160a01b0380851660248301528316604482015260648101829052610f2f9085906323b872dd60e01b906084016127d8565b6000856001600160a01b038082169086161415612897576001600160a01b038416301415612879576001915050610d70565b61288d6001600160a01b03821685886127ac565b6001915050610d70565b60008390506000816001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b1580156128d757600080fd5b505afa1580156128eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061290f919061452d565b90506060816001600160a01b03168a6001600160a01b031614806129445750816001600160a01b0316886001600160a01b0316145b156129f2576040805160028082526060820183529091602083019080368337019050509050898160008151811061298b57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505087816001815181106129cd57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050612ada565b6040805160038082526080820190925290602082016060803683370190505090508981600081518110612a3557634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b0316815250508181600181518110612a7757634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b0316815250508781600281518110612ab957634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b0316815250505b604051636eb1769f60e11b81523060048201526001600160a01b0387811660248301526000919086169063dd62ed3e9060440160206040518083038186803b158015612b2557600080fd5b505afa158015612b39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b5d91906149f9565b90508015612b7a57612b7a6001600160a01b038616886000613a17565b612b8e6001600160a01b038616888c613a17565b6005546000906001600160a01b038b811691161415612c48576000612bb28d613b42565b9050866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612bed57600080fd5b505afa158015612c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c259190614a34565b612c3090600a614e55565b612c3a828e614f00565b612c449190614df2565b9150505b604051635c11d79560e01b81526001600160a01b03861690635c11d79590612c7c908e90859088908f904290600401614d15565b600060405180830381600087803b158015612c9657600080fd5b505af1925050508015612ca7575060015b612ceb573d808015612cd5576040519150601f19603f3d011682016040523d82523d6000602084013e612cda565b606091505b506000975050505050505050610d70565b5060019b9a5050505050505050505050565b6000866001600160a01b038082169087161415612d4d576001600160a01b038416301415612d2f576001915050611335565b612d436001600160a01b03821685896127ac565b6001915050611335565b60008390506000816001600160a01b0316634aa4a4fc6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d8d57600080fd5b505afa158015612da1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dc5919061452d565b90506060816001600160a01b03168b6001600160a01b03161480612dfa5750816001600160a01b0316896001600160a01b0316145b15612ea0578a88600081518110612e2157634e487b7160e01b600052603260045260246000fd5b60200260200101518a604051602001612e8a93929190606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b6040516020818303038152906040529050612f79565b8a88600081518110612ec257634e487b7160e01b600052603260045260246000fd5b6020026020010151838a600181518110612eec57634e487b7160e01b600052603260045260246000fd5b6020908102919091018101516040516bffffffffffffffffffffffff19606096871b8116938201939093527fffffff000000000000000000000000000000000000000000000000000000000060e895861b8116603483015293861b83166037820152931b909116604b830152918b901b909116604e82015260620160405160208183030381529060405290505b604051636eb1769f60e11b81523060048201526001600160a01b0387811660248301526000919086169063dd62ed3e9060440160206040518083038186803b158015612fc457600080fd5b505afa158015612fd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ffc91906149f9565b90508015613019576130196001600160a01b038616886000613a17565b61302d6001600160a01b038616888d613a17565b6005546000906001600160a01b038c8116911614156130e75760006130518e613b42565b9050866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561308c57600080fd5b505afa1580156130a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130c49190614a34565b6130cf90600a614e55565b6130d9828f614f00565b6130e39190614df2565b9150505b604080516080810182528481526001600160a01b03808c1660208301528183018f905260608201849052915163b858183f60e01b8152909187169063b858183f90613136908490600401614cc6565b602060405180830381600087803b15801561315057600080fd5b505af1925050508015613180575060408051601f3d908101601f1916820190925261317d918101906149f9565b60015b6131c5573d8080156131ae576040519150601f19603f3d011682016040523d82523d6000602084013e6131b3565b606091505b50600098505050505050505050611335565b5060019e9d5050505050505050505050505050565b60006117be8383613d99565b6000610a7f825490565b600081815260018301602052604081205461323757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610a7f565b506000610a7f565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610ee75761327b816001600160a01b03166014613dd1565b613286836020613dd1565b604051602001613297929190614b7c565b60408051601f198184030181529082905262461bcd60e51b8252610b6591600401614cb3565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610ee7576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006117be836001600160a01b038416613fc0565b60006001600160a01b0382166133cf5760405162461bcd60e51b815260206004820152603f60248201527f4c50546f6b656e50726f636573736f7256323a3a5f737761705632546f6b656e60448201527f4279466565546f6b656e3a20556e737570706f7274656420726f757465722e006064820152608401610b65565b60405163095ea7b360e01b81526001600160a01b0383811660048301526024820185905285919082169063095ea7b390604401602060405180830381600087803b15801561341c57600080fd5b505af1158015613430573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134549190614792565b506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561349057600080fd5b505afa1580156134a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c8919061452d565b90506000826001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561350557600080fd5b505afa158015613519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353d919061452d565b604051635d5155ef60e11b81526001600160a01b03848116600483015280831660248301526044820189905260006064830181905260848301523060a48301524260c48301529192509086169063baa2abde9060e4016040805180830381600087803b1580156135ac57600080fd5b505af11580156135c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135e49190614a11565b50506040516370a0823160e01b815230600482015260009061367a9084906001600160a01b038216906370a08231906024015b60206040518083038186803b15801561362f57600080fd5b505afa158015613643573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061366791906149f9565b6005546001600160a01b0316308a612847565b9050806137155760405162461bcd60e51b815260206004820152604e60248201527f4c50546f6b656e50726f636573736f7256323a3a5f737761705632546f6b656e60448201527f4279466565546f6b656e3a204661696c656420746f207377617020746f6b656e60648201527f3020746f20666565546f6b656e2e000000000000000000000000000000000000608482015260a401610b65565b6040516370a0823160e01b81523060048201526137479083906001600160a01b038216906370a0823190602401613617565b9050806137e25760405162461bcd60e51b815260206004820152604e60248201527f4c50546f6b656e50726f636573736f7256323a3a5f737761705632546f6b656e60448201527f4279466565546f6b656e3a204661696c656420746f207377617020746f6b656e60648201527f3120746f20666565546f6b656e2e000000000000000000000000000000000000608482015260a401610b65565b50949695505050505050565b60006137fe8284608001516140dd565b60608401519091506001600160a01b0316156138c25760006127106138256109c485614f00565b61382f9190614df2565b905061383b8183614f1f565b606085015160055491935061385a916001600160a01b031690836127ac565b83608001516001600160a01b03166010547f0584abac593cbb9d01cfe5ec97b12619791d3cc06a0b945539d1ae5347dc3db58660600151846040516138b49291906001600160a01b03929092168252602082015260400190565b60405180910390a350436010555b6002546005546138df916001600160a01b039182169116836127ac565b82608001516001600160a01b0316600e547ff1d6c8ee14081f641e2073a1064d870f135f1001a301c6b14a7b9655672fec118360405161392191815260200190565b60405180910390a3505043600e5550565b6000613987826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661431d9092919063ffffffff16565b805190915015610e5a57808060200190518101906139a59190614792565b610e5a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610b65565b801580613aa05750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015613a6657600080fd5b505afa158015613a7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a9e91906149f9565b155b613b125760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610b65565b6040516001600160a01b038316602482015260448101829052610e5a90849063095ea7b360e01b906064016127d8565b6007546000906001600160a01b0316613b5d57506000919050565b60075460405163800e38b760e01b81526001600160a01b0384811660048301529091169063800e38b790602401600060405180830381600087803b158015613ba457600080fd5b505af1158015613bb8573d6000803e3d6000fd5b50506007546005546040805163313ce56760e01b81529051600095506001600160a01b039384169450637089f2bf938893169163313ce567916004808301926020929190829003018186803b158015613c1057600080fd5b505afa158015613c24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c489190614a34565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260ff16602482015260440160206040518083038186803b158015613c8f57600080fd5b505afa158015613ca3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cc791906149f9565b90506000811180613cdb5750600d5460ff16155b613d4d5760405162461bcd60e51b815260206004820152603960248201527f4c50546f6b656e50726f636573736f7256323a3a5f676574507269636557697460448201527f68536c6970706167653a205072696365206973207a65726f2e000000000000006064820152608401610b65565b6001600160a01b0383166000908152600c602052604090205480613d705750600b545b612710613d7d8284614f00565b613d879190614df2565b613d919083614f1f565b949350505050565b6000826000018281548110613dbe57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b60606000613de0836002614f00565b613deb906002614dda565b67ffffffffffffffff811115613e1157634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613e3b576020820181803683370190505b509050600360fc1b81600081518110613e6457634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110613ea157634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506000613ec5846002614f00565b613ed0906001614dda565b90505b6001811115613f71577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110613f1f57634e487b7160e01b600052603260045260246000fd5b1a60f81b828281518110613f4357634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c93613f6a81614f62565b9050613ed3565b5083156117be5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610b65565b600081815260018301602052604081205480156140d3576000613fe4600183614f1f565b8554909150600090613ff890600190614f1f565b905081811461407957600086600001828154811061402657634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061405757634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061409857634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610a7f565b6000915050610a7f565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161561431657600061271061411f6109c486614f00565b6141299190614df2565b90506141358185614f1f565b6040516370a0823160e01b815261dead60048201529094506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b15801561419c57600080fd5b505afa1580156141b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141d491906149f9565b60055460065491925061421b916001600160a01b039182169185917f00000000000000000000000000000000000000000000000000000000000000009161dead9116612847565b506040516370a0823160e01b815261dead600482015260009082906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319060240160206040518083038186803b15801561428257600080fd5b505afa158015614296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142ba91906149f9565b6142c49190614f1f565b600f5460408051898152602081018490529293506001600160a01b038816927f4124ef036039a90351b9862218c2417806e83bc3ec8152a46a64b6dc33f12d1f910160405180910390a3505043600f55505b5090919050565b6060613d918484600085856001600160a01b0385163b61437f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b65565b600080866001600160a01b0316858760405161439b9190614b60565b60006040518083038185875af1925050503d80600081146143d8576040519150601f19603f3d011682016040523d82523d6000602084013e6143dd565b606091505b50915091506143ed8282866143f8565b979650505050505050565b606083156144075750816117be565b8251156144175782518084602001fd5b8160405162461bcd60e51b8152600401610b659190614cb3565b508054600082556006029060005260206000209081019061209c91905b808211156144aa5780546001600160a01b031990811682556001820180546001600160a81b03191690556002820180548216905560038201805490911690556000600482015560058101805462ffffff1916905560060161444e565b5090565b80356144b981614fc0565b919050565b80516144b981614fc0565b8051600281900b81146144b957600080fd5b80516fffffffffffffffffffffffffffffffff811681146144b957600080fd5b80356144b981614fe3565b80516144b981614fe3565b600060208284031215614522578081fd5b81356117be81614fc0565b60006020828403121561453e578081fd5b81516117be81614fc0565b6000806040838503121561455b578081fd5b823561456681614fc0565b9150602083013561457681614fd5565b809150509250929050565b60008060408385031215614593578182fd5b823561459e81614fc0565b946020939093013593505050565b6000806000606084860312156145c0578081fd5b83356145cb81614fc0565b92506020840135915060408401356145e281614fc0565b809150509250925092565b60008060008060008060c08789031215614605578384fd5b863561461081614fc0565b95506020878101359550604088013561462881614fc0565b9450606088013561463881614fc0565b9350608088013561464881614fc0565b925060a088013567ffffffffffffffff811115614663578283fd5b8801601f81018a13614673578283fd5b803561468661468182614db6565b614d85565b8082825284820191508484018d868560051b87010111156146a5578687fd5b8694505b838510156146d05780356146bc81614fe3565b8352600194909401939185019185016146a9565b5080955050505050509295509295509295565b600060208083850312156146f5578182fd5b823567ffffffffffffffff81111561470b578283fd5b8301601f8101851361471b578283fd5b803561472961468182614db6565b80828252848201915084840188868560051b8701011115614748578687fd5b8694505b8385101561476a57803583526001949094019391850191850161474c565b50979650505050505050565b600060208284031215614787578081fd5b81356117be81614fd5565b6000602082840312156147a3578081fd5b81516117be81614fd5565b6000602082840312156147bf578081fd5b5035919050565b600080604083850312156147d8578182fd5b82359150602083013561457681614fc0565b600080604083850312156147fc578182fd5b50508035926020909101359150565b60006020828403121561481c578081fd5b81356001600160e01b0319811681146117be578182fd5b60008060208385031215614845578182fd5b823567ffffffffffffffff8082111561485c578384fd5b818501915085601f83011261486f578384fd5b81358181111561487d578485fd5b86602082850101111561488e578485fd5b60209290920196919550909350505050565b600060208083850312156148b2578182fd5b823567ffffffffffffffff808211156148c9578384fd5b818501915085601f8301126148dc578384fd5b8135818111156148ee576148ee614faa565b614900601f8201601f19168501614d85565b91508082528684828501011115614915578485fd5b80848401858401378101909201929092529392505050565b600060e0828403121561493e578081fd5b60405160e0810181811067ffffffffffffffff8211171561496157614961614faa565b604052823561496f81614fc0565b8152602083013561497f81614fc0565b6020820152604083013561499281614fd5565b604082015260608301356149a581614fc0565b60608201526149b6608084016144ae565b608082015260a083013560a08201526149d160c084016144fb565b60c08201529392505050565b6000602082840312156149ee578081fd5b81356117be81614fe3565b600060208284031215614a0a578081fd5b5051919050565b60008060408385031215614a23578182fd5b505080516020909101519092909150565b600060208284031215614a45578081fd5b815160ff811681146117be578182fd5b6000806000806000806000806000806000806101808d8f031215614a7757898afd5b8c516bffffffffffffffffffffffff81168114614a92578a8bfd5b9b50614aa060208e016144be565b9a50614aae60408e016144be565b9950614abc60608e016144be565b9850614aca60808e01614506565b9750614ad860a08e016144c9565b9650614ae660c08e016144c9565b9550614af460e08e016144db565b94506101008d015193506101208d01519250614b136101408e016144db565b9150614b226101608e016144db565b90509295989b509295989b509295989b565b60008151808452614b4c816020860160208601614f36565b601f01601f19169290920160200192915050565b60008251614b72818460208701614f36565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614bb4816017850160208801614f36565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614bf1816028840160208801614f36565b01602801949350505050565b602080825282518282018190526000919060409081850190868401855b82811015614c8b57815180516001600160a01b03908116865287820151811688870152868201511515878701526060808301518216908701526080808301519091169086015260a0808201519086015260c09081015162ffffff169085015260e09093019290850190600101614c1a565b5091979650505050505050565b8215158152604060208201526000613d916040830184614b34565b6020815260006117be6020830184614b34565b602081526000825160806020840152614ce260a0840182614b34565b90506001600160a01b03602085015116604084015260408401516060840152606084015160808401528091505092915050565b600060a082018783526020878185015260a0604085015281875180845260c0860191508289019350845b81811015614d645784516001600160a01b031683529383019391830191600101614d3f565b50506001600160a01b03969096166060850152505050608001529392505050565b604051601f8201601f1916810167ffffffffffffffff81118282101715614dae57614dae614faa565b604052919050565b600067ffffffffffffffff821115614dd057614dd0614faa565b5060051b60200190565b60008219821115614ded57614ded614f94565b500190565b600082614e0d57634e487b7160e01b81526012600452602481fd5b500490565b600181815b80851115614e4d578160001904821115614e3357614e33614f94565b80851615614e4057918102915b93841c9390800290614e17565b509250929050565b60006117be60ff841683600082614e6e57506001610a7f565b81614e7b57506000610a7f565b8160018114614e915760028114614e9b57614eb7565b6001915050610a7f565b60ff841115614eac57614eac614f94565b50506001821b610a7f565b5060208310610133831016604e8410600b8410161715614eda575081810a610a7f565b614ee48383614e12565b8060001904821115614ef857614ef8614f94565b029392505050565b6000816000190483118215151615614f1a57614f1a614f94565b500290565b600082821015614f3157614f31614f94565b500390565b60005b83811015614f51578181015183820152602001614f39565b83811115610f2f5750506000910152565b600081614f7157614f71614f94565b506000190190565b6000600019821415614f8d57614f8d614f94565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461209c57600080fd5b801515811461209c57600080fd5b62ffffff8116811461209c57600080fdfea164736f6c6343000804000a4c50546f6b656e50726f636573736f7256323a3a636f6e7374727563746f723a000000000000000000000000cf0c122c6b73ff809c693db761e7baebe62b6a2e00000000000000000000000000000000000000000000000000000000000002580000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000f5d492ffbec47db69333a6812bec227b6f670a860000000000000000000000004e8e826e6d64f711a383fa2e99e42f92a0a67d540000000000000000000000000000000000000000000000000000000000000bb8
Deployed Bytecode
0x6080604052600436106103385760003560e01c80636e04ff0d116101b0578063c60bb02e116100ec578063e23bfa5a11610095578063f1787dbe1161006f578063f1787dbe146109d9578063f426754214610a0f578063f79bcad014610a2f578063fccc281314610a4457600080fd5b8063e23bfa5a1461098d578063e39e927b146109a3578063ec49e921146109b957600080fd5b8063cd8afc00116100c6578063cd8afc00146108e6578063d547741f1461094d578063dee633631461096d57600080fd5b8063c60bb02e14610886578063ca15c873146108a6578063cab35423146108c657600080fd5b806391d14854116101595780639a436c9b116101335780639a436c9b146105cf5780639c76015a1461083b578063a217fddf1461085b578063c17036461461087057600080fd5b806391d14854146107b7578063951cfc82146107fb5780639654a3091461081b57600080fd5b80638369166d1161018a5780638369166d146107575780638b944542146107775780639010d07c1461079757600080fd5b80636e04ff0d146106db5780636e4e294f14610709578063809544741461073d57600080fd5b80632f9f8c131161027f57806352ef1da91161022857806356e1887d1161020257806356e1887d1461065b57806361d027b31461067b578063647846a51461069b5780636b27a811146106bb57600080fd5b806352ef1da914610605578063530e784f1461061b578063539c07c71461063b57600080fd5b80634585e33b116102595780634585e33b146105af578063470cc5f2146105cf578063495cdcde146105e557600080fd5b80632f9f8c131461054557806336568abe1461057957806344c6d80b1461059957600080fd5b806315cce224116102e1578063248a9ca3116102bb578063248a9ca3146104bd5780632630c12f146104ed5780632f2ff15d1461052557600080fd5b806315cce2241461045b5780631c3abd651461047b57806323a2e1a81461049b57600080fd5b806305f91e6f1161031257806305f91e6f146103d05780630aed36d01461040057806311eb1b861461042057600080fd5b806301ffc9a71461034457806302013695146103795780630400828c146103ae57600080fd5b3661033f57005b600080fd5b34801561035057600080fd5b5061036461035f36600461480b565b610a5a565b60405190151581526020015b60405180910390f35b34801561038557600080fd5b50600d5461039a90610100900462ffffff1681565b60405162ffffff9091168152602001610370565b3480156103ba57600080fd5b506103ce6103c93660046147ae565b610a85565b005b3480156103dc57600080fd5b506103646103eb366004614511565b60046020526000908152604090205460ff1681565b34801561040c57600080fd5b506103ce61041b366004614549565b610ad6565b34801561042c57600080fd5b5061044d61043b366004614511565b600c6020526000908152604090205481565b604051908152602001610370565b34801561046757600080fd5b506103ce610476366004614511565b610c3a565b34801561048757600080fd5b50610364610496366004614581565b610d3a565b3480156104a757600080fd5b506104b0610d79565b6040516103709190614bfd565b3480156104c957600080fd5b5061044d6104d83660046147ae565b60009081526020819052604090206001015490565b3480156104f957600080fd5b5060075461050d906001600160a01b031681565b6040516001600160a01b039091168152602001610370565b34801561053157600080fd5b506103ce6105403660046147c6565b610e35565b34801561055157600080fd5b5061050d7f000000000000000000000000cf0c122c6b73ff809c693db761e7baebe62b6a2e81565b34801561058557600080fd5b506103ce6105943660046147c6565b610e5f565b3480156105a557600080fd5b5061044d61271081565b3480156105bb57600080fd5b506103ce6105ca366004614833565b610eeb565b3480156105db57600080fd5b5061044d6109c481565b3480156105f157600080fd5b50610364610600366004614511565b610f35565b34801561061157600080fd5b5061044d600b5481565b34801561062757600080fd5b506103ce610636366004614511565b6110a0565b34801561064757600080fd5b5060065461050d906001600160a01b031681565b34801561066757600080fd5b506103ce6106763660046145ac565b6110fe565b34801561068757600080fd5b5060025461050d906001600160a01b031681565b3480156106a757600080fd5b5060055461050d906001600160a01b031681565b3480156106c757600080fd5b506103646106d63660046145ed565b6111d4565b3480156106e757600080fd5b506106fb6106f63660046148a0565b61133f565b604051610370929190614c98565b34801561071557600080fd5b5061044d7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c013681781565b34801561074957600080fd5b50600d546103649060ff1681565b34801561076357600080fd5b5061050d610772366004614511565b6114c5565b34801561078357600080fd5b506103ce610792366004614511565b61155f565b3480156107a357600080fd5b5061050d6107b23660046147ea565b6117a6565b3480156107c357600080fd5b506103646107d23660046147c6565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561080757600080fd5b506103ce6108163660046149dd565b6117c5565b34801561082757600080fd5b506103ce61083636600461492d565b6117f1565b34801561084757600080fd5b506103ce6108563660046147c6565b611b4c565b34801561086757600080fd5b5061044d600081565b34801561087c57600080fd5b5061044d60105481565b34801561089257600080fd5b506103ce6108a1366004614776565b611bbd565b3480156108b257600080fd5b5061044d6108c13660046147ae565b611bdc565b3480156108d257600080fd5b506103ce6108e13660046147ae565b611bf3565b3480156108f257600080fd5b50610906610901366004614581565b611c26565b604080516001600160a01b0395861681529490931660208501526fffffffffffffffffffffffffffffffff9091169183019190915262ffffff166060820152608001610370565b34801561095957600080fd5b506103ce6109683660046147c6565b611cdb565b34801561097957600080fd5b506103ce6109883660046146e3565b611d00565b34801561099957600080fd5b5061044d600e5481565b3480156109af57600080fd5b5061044d600f5481565b3480156109c557600080fd5b506103ce6109d43660046147ae565b611f84565b3480156109e557600080fd5b5061050d6109f4366004614511565b6003602052600090815260409020546001600160a01b031681565b348015610a1b57600080fd5b506103ce610a2a366004614511565b611fc9565b348015610a3b57600080fd5b506103ce612066565b348015610a5057600080fd5b5061050d61dead81565b60006001600160e01b03198216635a05180f60e01b1480610a7f5750610a7f82612152565b92915050565b6000610a9081612187565b600b80549083905560408051828152602081018590527f07af09e2b23ebab5dd29fa2271d6ca4795031f308caf26ca605f4a719ffeed61910160405180910390a1505050565b6000610ae181612187565b6001600160a01b038316610b6e5760405162461bcd60e51b815260206004820152604360248201527f4c50546f6b656e50726f636573736f7256323a3a616464526f757465723a3a5a60448201527f45524f3a20526f757465722063616e6e6f74206265207a65726f20616464726560648201526239b99760e91b608482015260a4015b60405180910390fd5b8260036000856001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b158015610bac57600080fd5b505afa158015610bc0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be4919061452d565b6001600160a01b0390811682526020808301939093526040918201600090812080546001600160a01b031916958316959095179094559590951682526004905292909220805460ff191691151591909117905550565b6000610c4581612187565b6001600160a01b038216610ce75760405162461bcd60e51b815260206004820152604760248201527f4c50546f6b656e50726f636573736f7256323a3a736574466565546f6b656e3a60448201527f3a5a45524f3a20666565546f6b656e2063616e6e6f74206265207a65726f206160648201527f6464726573732e00000000000000000000000000000000000000000000000000608482015260a401610b65565b600580546001600160a01b038481166001600160a01b0319831681179093556040519116919082907f91a03e1d689caf891fe531c01e290f7b718f9c6a3af6726d6d837d2b7bd82e6790600090a3505050565b6000806000610d498585611c26565b509193509150506001600160a01b03821615801590610d7057506001600160a01b03811615155b95945050505050565b6060600a805480602002602001604051908101604052809291908181526020016000905b82821015610e2c5760008481526020908190206040805160e0810182526006860290920180546001600160a01b03908116845260018083015480831686880152600160a01b900460ff161515938501939093526002820154811660608501526003820154166080840152600481015460a08401526005015462ffffff1660c08301529083529092019101610d9d565b50505050905090565b600082815260208190526040902060010154610e5081612187565b610e5a8383612191565b505050565b6001600160a01b0381163314610edd5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610b65565b610ee782826121b3565b5050565b600a5480610ef857505050565b60005b81811015610f2f576000610f0e826121d5565b90508015610f1c5750610f2f565b5080610f2781614f79565b915050610efb565b50505050565b60408051600481526024810182526020810180516001600160e01b0316630dfe168160e01b1790529051600091829160609183916001600160a01b03871691610f7d91614b60565b600060405180830381855afa9150503d8060008114610fb8576040519150601f19603f3d011682016040523d82523d6000602084013e610fbd565b606091505b50909350915082610fd357506000949350505050565b506020810151803b610fea57506000949350505050565b60408051600481526024810182526020810180516001600160e01b031663d21220a760e01b17905290516001600160a01b0387169161102891614b60565b600060405180830381855afa9150503d8060008114611063576040519150601f19603f3d011682016040523d82523d6000602084013e611068565b606091505b5090935091508261107e57506000949350505050565b506020810151803b61109557506000949350505050565b506001949350505050565b60006110ab81612187565b600780546001600160a01b038481166001600160a01b0319831681179093556040519116919082907f56b5f80d8cac1479698aa7d01605fd6111e90b15fc4d2b377417f46034876cbd90600090a3505050565b600061110981612187565b6001600160a01b0384166111c0576000826001600160a01b03168460405160006040518083038185875af1925050503d8060008114611164576040519150601f19603f3d011682016040523d82523d6000602084013e611169565b606091505b50509050806111ba5760405162461bcd60e51b815260206004820152601660248201527f4661696c656420746f20776974686472617720455448000000000000000000006044820152606401610b65565b50610f2f565b610f2f6001600160a01b03851683856127ac565b6040516370a0823160e01b815230600482015260009081906001600160a01b038916906370a082319060240160206040518083038186803b15801561121857600080fd5b505afa15801561122c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125091906149f9565b90506112676001600160a01b03891633308a61280f565b6040516370a0823160e01b815230600482015260009082906001600160a01b038b16906370a082319060240160206040518083038186803b1580156112ab57600080fd5b505afa1580156112bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e391906149f9565b6112ed9190614f1f565b6001600160a01b03861660009081526004602052604090205490915060ff16156113275761131e8982898989612847565b92505050611335565b61131e898289878a8a612cfd565b9695505050505050565b600a546000906060908061137b576040805160208082015260009181018290526060016040516020818303038152906040529250925050915091565b60005b818110156114be576000600a82815481106113a957634e487b7160e01b600052603260045260246000fd5b600091825260208083206040805160e081018252600690940290910180546001600160a01b0390811680865260018301548083168787015260ff600160a01b9091041615158685015260028301548216606087015260038301549091166080860152600482015460a086015260059091015462ffffff1660c0850152600854908552600990925290922054909250429161144291614dda565b10156114ab576020808201516001600160a01b03908116600090815260039092526040909120541680156114a957600160405160200161148d90602080825260009082015260400190565b6040516020818303038152906040529550955050505050915091565b505b50806114b681614f79565b91505061137e565b5050915091565b600060036000836001600160a01b031663c45a01556040518163ffffffff1660e01b815260040160206040518083038186803b15801561150457600080fd5b505afa158015611518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153c919061452d565b6001600160a01b0390811682526020820192909252604001600020541692915050565b7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c013681761158981612187565b600a545b8015610e5a576001600160a01b038316600a6115aa600184614f1f565b815481106115c857634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201546001600160a01b0316141561179457600a80546115f890600190614f1f565b8154811061161657634e487b7160e01b600052603260045260246000fd5b9060005260206000209060060201600a6001836116339190614f1f565b8154811061165157634e487b7160e01b600052603260045260246000fd5b60009182526020909120825460069092020180546001600160a01b03199081166001600160a01b039384161782556001808501805491840180548085169387169384178255915460ff600160a01b91829004161515026001600160a81b0319909216909217179055600280850154908301805483169185169190911790556003808501549083018054909216931692909217909155600480830154908201556005918201549101805462ffffff191662ffffff909216919091179055600a80548061172c57634e487b7160e01b600052603160045260246000fd5b60008281526020812060066000199093019283020180546001600160a01b031990811682556001820180546001600160a81b03191690556002820180548216905560038201805490911690556004810191909155600501805462ffffff191690559055505050565b8061179e81614f62565b91505061158d565b60008281526001602052604081206117be90836131da565b9392505050565b60006117d081612187565b50600d805462ffffff9092166101000263ffffff0019909216919091179055565b7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c013681761181b81612187565b81516040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561185e57600080fd5b505afa158015611872573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189691906149f9565b60a084015184519192506118b7916001600160a01b0316903390309061280f565b82516040516370a0823160e01b815230600482015260009183916001600160a01b03909116906370a082319060240160206040518083038186803b1580156118fe57600080fd5b505afa158015611912573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193691906149f9565b6119409190614f1f565b84516001600160a01b039081166000908152600960209081526040808320429055805160e081018252895185168152828a01518516928101928352818a015115158183019081526060808c015187169083019081526080808d0151881690840190815260a0840189815260c0808f015162ffffff908116918701918252600a8054600181018255908b5296517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8600690980297880180546001600160a01b0319908116928e1692909217905598517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a9880180549751918d166001600160a81b031990981697909717600160a01b911515919091021790955592517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2aa860180548916918b1691909117905590517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2ab850180549097169089161790955593517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2ac83015592517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2ad909101805462ffffff1916919093161790915587519051939450909116917f784c8f4dbf0ffedd6e72c76501c545a70f8b203b30a26ce542bf92ba87c248a49190a250505050565b6000611b5781612187565b6001600160a01b0382166000818152600c602090815260409182902080549087905582518181529182018790528183019390935290517fdbf456df41211767ed3f69868f89dce56871ab4769bcc87b0ffdebef7bb74abf9181900360600190a150505050565b6000611bc881612187565b50600d805460ff1916911515919091179055565b6000818152600160205260408120610a7f906131e6565b7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c0136817611c1d81612187565b610e5a826121d5565b600080600080856001600160a01b03166399fbab88866040518263ffffffff1660e01b8152600401611c5a91815260200190565b6101806040518083038186803b158015611c7357600080fd5b505afa925050508015611ca3575060408051601f3d908101601f19168201909252611ca091810190614a55565b60015b611cb857506000925082915081905080611cd2565b50979d50959b50909950929750611cd29650505050505050565b92959194509250565b600082815260208190526040902060010154611cf681612187565b610e5a83836121b3565b7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c0136817611d2a81612187565b60005b8251811015610e5a576000838281518110611d5857634e487b7160e01b600052603260045260246000fd5b602002602001015190506000600a8281548110611d8557634e487b7160e01b600052603260045260246000fd5b6000918252602090912060069091020154600a80546001600160a01b03909216925090611db490600190614f1f565b81548110611dd257634e487b7160e01b600052603260045260246000fd5b9060005260206000209060060201600a8381548110611e0157634e487b7160e01b600052603260045260246000fd5b60009182526020909120825460069092020180546001600160a01b03199081166001600160a01b039384161782556001808501805491840180548085169387169384178255915460ff600160a01b91829004161515026001600160a81b0319909216909217179055600280850154908301805483169185169190911790556003808501549083018054909216931692909217909155600480830154908201556005918201549101805462ffffff191662ffffff909216919091179055600a805480611edc57634e487b7160e01b600052603160045260246000fd5b60008281526020812060066000199093019283020180546001600160a01b031990811682556001820180546001600160a81b031916905560028201805482169055600382018054909116905560048101829055600501805462ffffff1916905591556040516001600160a01b038316917f4c910b69fe65a61f7531b9c5042b2329ca7179c77290aa7e2eb3afa3c8511fd391a250508080611f7c90614f79565b915050611d2d565b6000611f8f81612187565b6008805490839055604051839082907f7ff6561fd143a7a81e57b057370065fec411691ad4ea760fcdd900587f35ba2990600090a3505050565b7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c0136817611ff381612187565b60005b600a54811015610e5a57826001600160a01b0316600a828154811061202b57634e487b7160e01b600052603260045260246000fd5b60009182526020909120600690910201546001600160a01b0316141561205457610f2f816121d5565b8061205e81614f79565b915050611ff6565b7f53314c6c94ad7090bf88f7cf797a3546615cca0693e09e2de2cb72c9c013681761209081612187565b61209c600a6000614431565b50565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610ee7576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556120f93390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006117be836001600160a01b0384166131f0565b60006001600160e01b03198216637965db0b60e01b1480610a7f57506301ffc9a760e01b6001600160e01b0319831614610a7f565b61209c813361323f565b61219b828261209f565b6000828152600160205260409020610e5a908261213d565b6121bd82826132bd565b6000828152600160205260409020610e5a908261333c565b600080600a83815481106121f957634e487b7160e01b600052603260045260246000fd5b600091825260208083206040805160e08101825260069490940290910180546001600160a01b0390811685526001820154808216868601819052600160a01b90910460ff1615158685015260028301548216606087015260038084015483166080880152600484015460a088015260059093015462ffffff1660c087015286529252909220549092501680612292575060009392505050565b60085482516001600160a01b031660009081526009602052604090205442916122ba91614dda565b106122c9575060009392505050565b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561230d57600080fd5b505afa158015612321573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061234591906149f9565b905082604001511561236a5761236483600001518460a0015184613351565b5061250f565b6001600160a01b03821660009081526004602052604081205460ff16156123b257835160a08501516005546123ab9291906001600160a01b03163087612847565b9050612474565b6040805160028082526060820183526000926020830190803683370190505090508460c00151816000815181106123f957634e487b7160e01b600052603260045260246000fd5b62ffffff9283166020918202929092010152600d548251610100909104909116908290600190811061243b57634e487b7160e01b600052603260045260246000fd5b62ffffff90921660209283029190910190910152845160a08601516005546124709291906001600160a01b0316843089612cfd565b9150505b8061250d5760405162461bcd60e51b815260206004820152604a60248201527f4c50546f6b656e50726f636573736f7256323a3a706572666f726d55706b656560448201527f703a204661696c656420746f207377617020455243323020746f6b656e20627960648201527f20666565546f6b656e2e00000000000000000000000000000000000000000000608482015260a401610b65565b505b6005546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561255357600080fd5b505afa158015612567573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258b91906149f9565b60055485519192506001600160a01b03918216911614156125b85760a08401516125b59082614dda565b90505b60006125c48383614f1f565b90506125d085826137ee565b600a80546125e090600190614f1f565b815481106125fe57634e487b7160e01b600052603260045260246000fd5b9060005260206000209060060201600a888154811061262d57634e487b7160e01b600052603260045260246000fd5b60009182526020909120825460069092020180546001600160a01b03199081166001600160a01b039384161782556001808501805491840180548085169387169384178255915460ff600160a01b91829004161515026001600160a81b0319909216909217179055600280850154908301805483169185169190911790556003808501549083018054909216931692909217909155600480830154908201556005918201549101805462ffffff191662ffffff909216919091179055600a80548061270857634e487b7160e01b600052603160045260246000fd5b60008281526020812060066000199093019283020180546001600160a01b031990811682556001820180546001600160a81b031916905560028201805482169055600382018054909116905560048101829055600501805462ffffff19169055915585516040516001600160a01b0391909116917fd5512cb11a9597e816b26c674dbb6372fbb9c1bb69e088a8d0841b493db03fa491a25060019695505050505050565b6040516001600160a01b038316602482015260448101829052610e5a90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613932565b6040516001600160a01b0380851660248301528316604482015260648101829052610f2f9085906323b872dd60e01b906084016127d8565b6000856001600160a01b038082169086161415612897576001600160a01b038416301415612879576001915050610d70565b61288d6001600160a01b03821685886127ac565b6001915050610d70565b60008390506000816001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b1580156128d757600080fd5b505afa1580156128eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061290f919061452d565b90506060816001600160a01b03168a6001600160a01b031614806129445750816001600160a01b0316886001600160a01b0316145b156129f2576040805160028082526060820183529091602083019080368337019050509050898160008151811061298b57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b03168152505087816001815181106129cd57634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b031681525050612ada565b6040805160038082526080820190925290602082016060803683370190505090508981600081518110612a3557634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b0316815250508181600181518110612a7757634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b0316815250508781600281518110612ab957634e487b7160e01b600052603260045260246000fd5b60200260200101906001600160a01b031690816001600160a01b0316815250505b604051636eb1769f60e11b81523060048201526001600160a01b0387811660248301526000919086169063dd62ed3e9060440160206040518083038186803b158015612b2557600080fd5b505afa158015612b39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b5d91906149f9565b90508015612b7a57612b7a6001600160a01b038616886000613a17565b612b8e6001600160a01b038616888c613a17565b6005546000906001600160a01b038b811691161415612c48576000612bb28d613b42565b9050866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612bed57600080fd5b505afa158015612c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c259190614a34565b612c3090600a614e55565b612c3a828e614f00565b612c449190614df2565b9150505b604051635c11d79560e01b81526001600160a01b03861690635c11d79590612c7c908e90859088908f904290600401614d15565b600060405180830381600087803b158015612c9657600080fd5b505af1925050508015612ca7575060015b612ceb573d808015612cd5576040519150601f19603f3d011682016040523d82523d6000602084013e612cda565b606091505b506000975050505050505050610d70565b5060019b9a5050505050505050505050565b6000866001600160a01b038082169087161415612d4d576001600160a01b038416301415612d2f576001915050611335565b612d436001600160a01b03821685896127ac565b6001915050611335565b60008390506000816001600160a01b0316634aa4a4fc6040518163ffffffff1660e01b815260040160206040518083038186803b158015612d8d57600080fd5b505afa158015612da1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dc5919061452d565b90506060816001600160a01b03168b6001600160a01b03161480612dfa5750816001600160a01b0316896001600160a01b0316145b15612ea0578a88600081518110612e2157634e487b7160e01b600052603260045260246000fd5b60200260200101518a604051602001612e8a93929190606093841b6bffffffffffffffffffffffff19908116825260e89390931b7fffffff0000000000000000000000000000000000000000000000000000000000166014820152921b166017820152602b0190565b6040516020818303038152906040529050612f79565b8a88600081518110612ec257634e487b7160e01b600052603260045260246000fd5b6020026020010151838a600181518110612eec57634e487b7160e01b600052603260045260246000fd5b6020908102919091018101516040516bffffffffffffffffffffffff19606096871b8116938201939093527fffffff000000000000000000000000000000000000000000000000000000000060e895861b8116603483015293861b83166037820152931b909116604b830152918b901b909116604e82015260620160405160208183030381529060405290505b604051636eb1769f60e11b81523060048201526001600160a01b0387811660248301526000919086169063dd62ed3e9060440160206040518083038186803b158015612fc457600080fd5b505afa158015612fd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ffc91906149f9565b90508015613019576130196001600160a01b038616886000613a17565b61302d6001600160a01b038616888d613a17565b6005546000906001600160a01b038c8116911614156130e75760006130518e613b42565b9050866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561308c57600080fd5b505afa1580156130a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130c49190614a34565b6130cf90600a614e55565b6130d9828f614f00565b6130e39190614df2565b9150505b604080516080810182528481526001600160a01b03808c1660208301528183018f905260608201849052915163b858183f60e01b8152909187169063b858183f90613136908490600401614cc6565b602060405180830381600087803b15801561315057600080fd5b505af1925050508015613180575060408051601f3d908101601f1916820190925261317d918101906149f9565b60015b6131c5573d8080156131ae576040519150601f19603f3d011682016040523d82523d6000602084013e6131b3565b606091505b50600098505050505050505050611335565b5060019e9d5050505050505050505050505050565b60006117be8383613d99565b6000610a7f825490565b600081815260018301602052604081205461323757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610a7f565b506000610a7f565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16610ee75761327b816001600160a01b03166014613dd1565b613286836020613dd1565b604051602001613297929190614b7c565b60408051601f198184030181529082905262461bcd60e51b8252610b6591600401614cb3565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1615610ee7576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006117be836001600160a01b038416613fc0565b60006001600160a01b0382166133cf5760405162461bcd60e51b815260206004820152603f60248201527f4c50546f6b656e50726f636573736f7256323a3a5f737761705632546f6b656e60448201527f4279466565546f6b656e3a20556e737570706f7274656420726f757465722e006064820152608401610b65565b60405163095ea7b360e01b81526001600160a01b0383811660048301526024820185905285919082169063095ea7b390604401602060405180830381600087803b15801561341c57600080fd5b505af1158015613430573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134549190614792565b506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561349057600080fd5b505afa1580156134a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134c8919061452d565b90506000826001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b15801561350557600080fd5b505afa158015613519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061353d919061452d565b604051635d5155ef60e11b81526001600160a01b03848116600483015280831660248301526044820189905260006064830181905260848301523060a48301524260c48301529192509086169063baa2abde9060e4016040805180830381600087803b1580156135ac57600080fd5b505af11580156135c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135e49190614a11565b50506040516370a0823160e01b815230600482015260009061367a9084906001600160a01b038216906370a08231906024015b60206040518083038186803b15801561362f57600080fd5b505afa158015613643573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061366791906149f9565b6005546001600160a01b0316308a612847565b9050806137155760405162461bcd60e51b815260206004820152604e60248201527f4c50546f6b656e50726f636573736f7256323a3a5f737761705632546f6b656e60448201527f4279466565546f6b656e3a204661696c656420746f207377617020746f6b656e60648201527f3020746f20666565546f6b656e2e000000000000000000000000000000000000608482015260a401610b65565b6040516370a0823160e01b81523060048201526137479083906001600160a01b038216906370a0823190602401613617565b9050806137e25760405162461bcd60e51b815260206004820152604e60248201527f4c50546f6b656e50726f636573736f7256323a3a5f737761705632546f6b656e60448201527f4279466565546f6b656e3a204661696c656420746f207377617020746f6b656e60648201527f3120746f20666565546f6b656e2e000000000000000000000000000000000000608482015260a401610b65565b50949695505050505050565b60006137fe8284608001516140dd565b60608401519091506001600160a01b0316156138c25760006127106138256109c485614f00565b61382f9190614df2565b905061383b8183614f1f565b606085015160055491935061385a916001600160a01b031690836127ac565b83608001516001600160a01b03166010547f0584abac593cbb9d01cfe5ec97b12619791d3cc06a0b945539d1ae5347dc3db58660600151846040516138b49291906001600160a01b03929092168252602082015260400190565b60405180910390a350436010555b6002546005546138df916001600160a01b039182169116836127ac565b82608001516001600160a01b0316600e547ff1d6c8ee14081f641e2073a1064d870f135f1001a301c6b14a7b9655672fec118360405161392191815260200190565b60405180910390a3505043600e5550565b6000613987826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661431d9092919063ffffffff16565b805190915015610e5a57808060200190518101906139a59190614792565b610e5a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610b65565b801580613aa05750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e9060440160206040518083038186803b158015613a6657600080fd5b505afa158015613a7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a9e91906149f9565b155b613b125760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610b65565b6040516001600160a01b038316602482015260448101829052610e5a90849063095ea7b360e01b906064016127d8565b6007546000906001600160a01b0316613b5d57506000919050565b60075460405163800e38b760e01b81526001600160a01b0384811660048301529091169063800e38b790602401600060405180830381600087803b158015613ba457600080fd5b505af1158015613bb8573d6000803e3d6000fd5b50506007546005546040805163313ce56760e01b81529051600095506001600160a01b039384169450637089f2bf938893169163313ce567916004808301926020929190829003018186803b158015613c1057600080fd5b505afa158015613c24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c489190614a34565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260ff16602482015260440160206040518083038186803b158015613c8f57600080fd5b505afa158015613ca3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cc791906149f9565b90506000811180613cdb5750600d5460ff16155b613d4d5760405162461bcd60e51b815260206004820152603960248201527f4c50546f6b656e50726f636573736f7256323a3a5f676574507269636557697460448201527f68536c6970706167653a205072696365206973207a65726f2e000000000000006064820152608401610b65565b6001600160a01b0383166000908152600c602052604090205480613d705750600b545b612710613d7d8284614f00565b613d879190614df2565b613d919083614f1f565b949350505050565b6000826000018281548110613dbe57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b60606000613de0836002614f00565b613deb906002614dda565b67ffffffffffffffff811115613e1157634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015613e3b576020820181803683370190505b509050600360fc1b81600081518110613e6457634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110613ea157634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053506000613ec5846002614f00565b613ed0906001614dda565b90505b6001811115613f71577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110613f1f57634e487b7160e01b600052603260045260246000fd5b1a60f81b828281518110613f4357634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c93613f6a81614f62565b9050613ed3565b5083156117be5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610b65565b600081815260018301602052604081205480156140d3576000613fe4600183614f1f565b8554909150600090613ff890600190614f1f565b905081811461407957600086600001828154811061402657634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061405757634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b855486908061409857634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610a7f565b6000915050610a7f565b60007f000000000000000000000000cf0c122c6b73ff809c693db761e7baebe62b6a2e6001600160a01b03161561431657600061271061411f6109c486614f00565b6141299190614df2565b90506141358185614f1f565b6040516370a0823160e01b815261dead60048201529094506000906001600160a01b037f000000000000000000000000cf0c122c6b73ff809c693db761e7baebe62b6a2e16906370a082319060240160206040518083038186803b15801561419c57600080fd5b505afa1580156141b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141d491906149f9565b60055460065491925061421b916001600160a01b039182169185917f000000000000000000000000cf0c122c6b73ff809c693db761e7baebe62b6a2e9161dead9116612847565b506040516370a0823160e01b815261dead600482015260009082906001600160a01b037f000000000000000000000000cf0c122c6b73ff809c693db761e7baebe62b6a2e16906370a082319060240160206040518083038186803b15801561428257600080fd5b505afa158015614296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142ba91906149f9565b6142c49190614f1f565b600f5460408051898152602081018490529293506001600160a01b038816927f4124ef036039a90351b9862218c2417806e83bc3ec8152a46a64b6dc33f12d1f910160405180910390a3505043600f55505b5090919050565b6060613d918484600085856001600160a01b0385163b61437f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b65565b600080866001600160a01b0316858760405161439b9190614b60565b60006040518083038185875af1925050503d80600081146143d8576040519150601f19603f3d011682016040523d82523d6000602084013e6143dd565b606091505b50915091506143ed8282866143f8565b979650505050505050565b606083156144075750816117be565b8251156144175782518084602001fd5b8160405162461bcd60e51b8152600401610b659190614cb3565b508054600082556006029060005260206000209081019061209c91905b808211156144aa5780546001600160a01b031990811682556001820180546001600160a81b03191690556002820180548216905560038201805490911690556000600482015560058101805462ffffff1916905560060161444e565b5090565b80356144b981614fc0565b919050565b80516144b981614fc0565b8051600281900b81146144b957600080fd5b80516fffffffffffffffffffffffffffffffff811681146144b957600080fd5b80356144b981614fe3565b80516144b981614fe3565b600060208284031215614522578081fd5b81356117be81614fc0565b60006020828403121561453e578081fd5b81516117be81614fc0565b6000806040838503121561455b578081fd5b823561456681614fc0565b9150602083013561457681614fd5565b809150509250929050565b60008060408385031215614593578182fd5b823561459e81614fc0565b946020939093013593505050565b6000806000606084860312156145c0578081fd5b83356145cb81614fc0565b92506020840135915060408401356145e281614fc0565b809150509250925092565b60008060008060008060c08789031215614605578384fd5b863561461081614fc0565b95506020878101359550604088013561462881614fc0565b9450606088013561463881614fc0565b9350608088013561464881614fc0565b925060a088013567ffffffffffffffff811115614663578283fd5b8801601f81018a13614673578283fd5b803561468661468182614db6565b614d85565b8082825284820191508484018d868560051b87010111156146a5578687fd5b8694505b838510156146d05780356146bc81614fe3565b8352600194909401939185019185016146a9565b5080955050505050509295509295509295565b600060208083850312156146f5578182fd5b823567ffffffffffffffff81111561470b578283fd5b8301601f8101851361471b578283fd5b803561472961468182614db6565b80828252848201915084840188868560051b8701011115614748578687fd5b8694505b8385101561476a57803583526001949094019391850191850161474c565b50979650505050505050565b600060208284031215614787578081fd5b81356117be81614fd5565b6000602082840312156147a3578081fd5b81516117be81614fd5565b6000602082840312156147bf578081fd5b5035919050565b600080604083850312156147d8578182fd5b82359150602083013561457681614fc0565b600080604083850312156147fc578182fd5b50508035926020909101359150565b60006020828403121561481c578081fd5b81356001600160e01b0319811681146117be578182fd5b60008060208385031215614845578182fd5b823567ffffffffffffffff8082111561485c578384fd5b818501915085601f83011261486f578384fd5b81358181111561487d578485fd5b86602082850101111561488e578485fd5b60209290920196919550909350505050565b600060208083850312156148b2578182fd5b823567ffffffffffffffff808211156148c9578384fd5b818501915085601f8301126148dc578384fd5b8135818111156148ee576148ee614faa565b614900601f8201601f19168501614d85565b91508082528684828501011115614915578485fd5b80848401858401378101909201929092529392505050565b600060e0828403121561493e578081fd5b60405160e0810181811067ffffffffffffffff8211171561496157614961614faa565b604052823561496f81614fc0565b8152602083013561497f81614fc0565b6020820152604083013561499281614fd5565b604082015260608301356149a581614fc0565b60608201526149b6608084016144ae565b608082015260a083013560a08201526149d160c084016144fb565b60c08201529392505050565b6000602082840312156149ee578081fd5b81356117be81614fe3565b600060208284031215614a0a578081fd5b5051919050565b60008060408385031215614a23578182fd5b505080516020909101519092909150565b600060208284031215614a45578081fd5b815160ff811681146117be578182fd5b6000806000806000806000806000806000806101808d8f031215614a7757898afd5b8c516bffffffffffffffffffffffff81168114614a92578a8bfd5b9b50614aa060208e016144be565b9a50614aae60408e016144be565b9950614abc60608e016144be565b9850614aca60808e01614506565b9750614ad860a08e016144c9565b9650614ae660c08e016144c9565b9550614af460e08e016144db565b94506101008d015193506101208d01519250614b136101408e016144db565b9150614b226101608e016144db565b90509295989b509295989b509295989b565b60008151808452614b4c816020860160208601614f36565b601f01601f19169290920160200192915050565b60008251614b72818460208701614f36565b9190910192915050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260008351614bb4816017850160208801614f36565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351614bf1816028840160208801614f36565b01602801949350505050565b602080825282518282018190526000919060409081850190868401855b82811015614c8b57815180516001600160a01b03908116865287820151811688870152868201511515878701526060808301518216908701526080808301519091169086015260a0808201519086015260c09081015162ffffff169085015260e09093019290850190600101614c1a565b5091979650505050505050565b8215158152604060208201526000613d916040830184614b34565b6020815260006117be6020830184614b34565b602081526000825160806020840152614ce260a0840182614b34565b90506001600160a01b03602085015116604084015260408401516060840152606084015160808401528091505092915050565b600060a082018783526020878185015260a0604085015281875180845260c0860191508289019350845b81811015614d645784516001600160a01b031683529383019391830191600101614d3f565b50506001600160a01b03969096166060850152505050608001529392505050565b604051601f8201601f1916810167ffffffffffffffff81118282101715614dae57614dae614faa565b604052919050565b600067ffffffffffffffff821115614dd057614dd0614faa565b5060051b60200190565b60008219821115614ded57614ded614f94565b500190565b600082614e0d57634e487b7160e01b81526012600452602481fd5b500490565b600181815b80851115614e4d578160001904821115614e3357614e33614f94565b80851615614e4057918102915b93841c9390800290614e17565b509250929050565b60006117be60ff841683600082614e6e57506001610a7f565b81614e7b57506000610a7f565b8160018114614e915760028114614e9b57614eb7565b6001915050610a7f565b60ff841115614eac57614eac614f94565b50506001821b610a7f565b5060208310610133831016604e8410600b8410161715614eda575081810a610a7f565b614ee48383614e12565b8060001904821115614ef857614ef8614f94565b029392505050565b6000816000190483118215151615614f1a57614f1a614f94565b500290565b600082821015614f3157614f31614f94565b500390565b60005b83811015614f51578181015183820152602001614f39565b83811115610f2f5750506000910152565b600081614f7157614f71614f94565b506000190190565b6000600019821415614f8d57614f8d614f94565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461209c57600080fd5b801515811461209c57600080fd5b62ffffff8116811461209c57600080fdfea164736f6c6343000804000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000cf0c122c6b73ff809c693db761e7baebe62b6a2e00000000000000000000000000000000000000000000000000000000000002580000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000f5d492ffbec47db69333a6812bec227b6f670a860000000000000000000000004e8e826e6d64f711a383fa2e99e42f92a0a67d540000000000000000000000000000000000000000000000000000000000000bb8
-----Decoded View---------------
Arg [0] : flokiAddress (address): 0xcf0C122c6b73ff809C693DB761e7BaeBe62b6a2E
Arg [1] : sellDelay (uint256): 600
Arg [2] : mainRouter (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
Arg [3] : isV2Router (bool): True
Arg [4] : feeTokenAddress (address): 0xdAC17F958D2ee523a2206206994597C13D831ec7
Arg [5] : treasuryAddress (address): 0xf5d492fFBeC47DB69333A6812bEc227B6f670A86
Arg [6] : priceOracleAddress (address): 0x4e8E826E6d64f711A383fA2e99e42F92a0A67d54
Arg [7] : v3DefaultPoolFee (uint24): 3000
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000cf0c122c6b73ff809c693db761e7baebe62b6a2e
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000258
Arg [2] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [4] : 000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7
Arg [5] : 000000000000000000000000f5d492ffbec47db69333a6812bec227b6f670a86
Arg [6] : 0000000000000000000000004e8e826e6d64f711a383fa2e99e42f92a0a67d54
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000bb8
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.