More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 37 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw All To ... | 53529355 | 709 days ago | IN | 0 FTM | 0.00267996 | ||||
Withdraw All To ... | 53529350 | 709 days ago | IN | 0 FTM | 0.00263759 | ||||
Withdraw All To ... | 53529345 | 709 days ago | IN | 0 FTM | 0.00263575 | ||||
Withdraw All To ... | 53529339 | 709 days ago | IN | 0 FTM | 0.00272463 | ||||
Pause | 53478243 | 710 days ago | IN | 0 FTM | 0.00275757 | ||||
Unpause | 51912418 | 745 days ago | IN | 0 FTM | 0.00069641 | ||||
Pause | 51899524 | 745 days ago | IN | 0 FTM | 0.00252113 | ||||
Withdraw All To ... | 51424124 | 755 days ago | IN | 0 FTM | 0.00701149 | ||||
Withdraw All To ... | 51420475 | 755 days ago | IN | 0 FTM | 0.00451945 | ||||
Withdraw All To ... | 51411196 | 755 days ago | IN | 0 FTM | 0.01077429 | ||||
Unpause | 51230095 | 759 days ago | IN | 0 FTM | 0.00196434 | ||||
Pause | 51216109 | 759 days ago | IN | 0 FTM | 0.11265313 | ||||
Unpause | 50768362 | 768 days ago | IN | 0 FTM | 0.01679959 | ||||
Pause | 50726668 | 769 days ago | IN | 0 FTM | 0.08602754 | ||||
Unpause | 49880358 | 787 days ago | IN | 0 FTM | 0.00003014 | ||||
Pause | 49870719 | 787 days ago | IN | 0 FTM | 0.01405174 | ||||
Unpause | 47990207 | 812 days ago | IN | 0 FTM | 0.00003429 | ||||
Pause | 47979773 | 812 days ago | IN | 0 FTM | 0.00011434 | ||||
Unpause | 46572367 | 833 days ago | IN | 0 FTM | 0.00008707 | ||||
Pause | 46563760 | 833 days ago | IN | 0 FTM | 0.00257755 | ||||
Unpause | 45146175 | 854 days ago | IN | 0 FTM | 0.00004124 | ||||
Pause | 45139086 | 854 days ago | IN | 0 FTM | 0.0186872 | ||||
Unpause | 40907785 | 913 days ago | IN | 0 FTM | 0.0003382 | ||||
Pause | 40879566 | 913 days ago | IN | 0 FTM | 0.00152489 | ||||
Claim Ownership | 40204134 | 922 days ago | IN | 0 FTM | 0.00048898 |
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
35475008 | 986 days ago | Contract Creation | 0 FTM |
Loading...
Loading
Contract Name:
WooPP
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity =0.6.12; pragma experimental ABIEncoderV2; /* ░██╗░░░░░░░██╗░█████╗░░█████╗░░░░░░░███████╗██╗ ░██║░░██╗░░██║██╔══██╗██╔══██╗░░░░░░██╔════╝██║ ░╚██╗████╗██╔╝██║░░██║██║░░██║█████╗█████╗░░██║ ░░████╔═████║░██║░░██║██║░░██║╚════╝██╔══╝░░██║ ░░╚██╔╝░╚██╔╝░╚█████╔╝╚█████╔╝░░░░░░██║░░░░░██║ ░░░╚═╝░░░╚═╝░░░╚════╝░░╚════╝░░░░░░░╚═╝░░░░░╚═╝ * * MIT License * =========== * * Copyright (c) 2020 WooTrade * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ import './libraries/InitializableOwnable.sol'; import './libraries/DecimalMath.sol'; import './interfaces/IWooracle.sol'; import './interfaces/IWooPP.sol'; import './interfaces/IWooFeeManager.sol'; import './interfaces/IWooGuardian.sol'; import './interfaces/AggregatorV3Interface.sol'; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '@openzeppelin/contracts/token/ERC20/ERC20.sol'; import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol'; import '@openzeppelin/contracts/utils/ReentrancyGuard.sol'; import '@openzeppelin/contracts/utils/Pausable.sol'; import '@openzeppelin/contracts/math/SafeMath.sol'; import '@uniswap/lib/contracts/libraries/TransferHelper.sol'; /// @title Woo private pool for swaping. /// @notice the implementation class for interface IWooPP, mainly for query and swap tokens. contract WooPP is InitializableOwnable, ReentrancyGuard, Pausable, IWooPP { /* ----- Type declarations ----- */ using SafeMath for uint256; using DecimalMath for uint256; using SafeERC20 for IERC20; /* ----- State variables ----- */ mapping(address => TokenInfo) public tokenInfo; mapping(address => bool) public isStrategist; /// @inheritdoc IWooPP address public immutable override quoteToken; address public wooracle; IWooGuardian public wooGuardian; IWooFeeManager public feeManager; string public pairsInfo; // e.g. BNB/ETH/BTCB/WOO-USDT /* ----- Modifiers ----- */ modifier onlyStrategist() { require(msg.sender == _OWNER_ || isStrategist[msg.sender], 'WooPP: NOT_STRATEGIST'); _; } constructor( address newQuoteToken, address newWooracle, address newFeeManager, address newWooGuardian ) public { require(newQuoteToken != address(0), 'WooPP: INVALID_QUOTE'); require(newWooracle != address(0), 'WooPP: newWooracle_ZERO_ADDR'); require(newFeeManager != address(0), 'WooPP: newFeeManager_ZERO_ADDR'); require(newWooGuardian != address(0), 'WooPP: newWooGuardian_ZERO_ADDR'); initOwner(msg.sender); quoteToken = newQuoteToken; wooracle = newWooracle; feeManager = IWooFeeManager(newFeeManager); require(feeManager.quoteToken() == newQuoteToken, 'WooPP: feeManager_quoteToken_INVALID'); wooGuardian = IWooGuardian(newWooGuardian); TokenInfo storage quoteInfo = tokenInfo[newQuoteToken]; quoteInfo.isValid = true; } /* ----- External Functions ----- */ /// @inheritdoc IWooPP function querySellBase(address baseToken, uint256 baseAmount) external view override whenNotPaused returns (uint256 quoteAmount) { require(baseToken != address(0), 'WooPP: baseToken_ZERO_ADDR'); require(baseToken != quoteToken, 'WooPP: baseToken==quoteToken'); wooGuardian.checkInputAmount(baseToken, baseAmount); TokenInfo memory baseInfo = tokenInfo[baseToken]; require(baseInfo.isValid, 'WooPP: TOKEN_DOES_NOT_EXIST'); TokenInfo memory quoteInfo = tokenInfo[quoteToken]; _autoUpdate(baseToken, baseInfo, quoteInfo); quoteAmount = getQuoteAmountSellBase(baseToken, baseAmount, baseInfo, quoteInfo); wooGuardian.checkSwapAmount(baseToken, quoteToken, baseAmount, quoteAmount); uint256 lpFee = quoteAmount.mulCeil(feeManager.feeRate(baseToken)); quoteAmount = quoteAmount.sub(lpFee); require(quoteAmount <= IERC20(quoteToken).balanceOf(address(this)), 'WooPP: INSUFF_QUOTE'); } /// @inheritdoc IWooPP function querySellQuote(address baseToken, uint256 quoteAmount) external view override whenNotPaused returns (uint256 baseAmount) { require(baseToken != address(0), 'WooPP: baseToken_ZERO_ADDR'); require(baseToken != quoteToken, 'WooPP: baseToken==quoteToken'); wooGuardian.checkInputAmount(quoteToken, quoteAmount); TokenInfo memory baseInfo = tokenInfo[baseToken]; require(baseInfo.isValid, 'WooPP: TOKEN_DOES_NOT_EXIST'); TokenInfo memory quoteInfo = tokenInfo[quoteToken]; _autoUpdate(baseToken, baseInfo, quoteInfo); uint256 lpFee = quoteAmount.mulCeil(feeManager.feeRate(baseToken)); quoteAmount = quoteAmount.sub(lpFee); baseAmount = getBaseAmountSellQuote(baseToken, quoteAmount, baseInfo, quoteInfo); wooGuardian.checkSwapAmount(quoteToken, baseToken, quoteAmount, baseAmount); require(baseAmount <= IERC20(baseToken).balanceOf(address(this)), 'WooPP: INSUFF_BASE'); } /// @inheritdoc IWooPP function sellBase( address baseToken, uint256 baseAmount, uint256 minQuoteAmount, address to, address rebateTo ) external override nonReentrant whenNotPaused returns (uint256 quoteAmount) { require(baseToken != address(0), 'WooPP: baseToken_ZERO_ADDR'); require(to != address(0), 'WooPP: to_ZERO_ADDR'); require(baseToken != quoteToken, 'WooPP: baseToken==quoteToken'); wooGuardian.checkInputAmount(baseToken, baseAmount); address from = msg.sender; TokenInfo memory baseInfo = tokenInfo[baseToken]; require(baseInfo.isValid, 'WooPP: TOKEN_DOES_NOT_EXIST'); TokenInfo memory quoteInfo = tokenInfo[quoteToken]; _autoUpdate(baseToken, baseInfo, quoteInfo); TransferHelper.safeTransferFrom(baseToken, from, address(this), baseAmount); quoteAmount = getQuoteAmountSellBase(baseToken, baseAmount, baseInfo, quoteInfo); wooGuardian.checkSwapAmount(baseToken, quoteToken, baseAmount, quoteAmount); uint256 lpFee = quoteAmount.mulCeil(feeManager.feeRate(baseToken)); quoteAmount = quoteAmount.sub(lpFee); require(quoteAmount >= minQuoteAmount, 'WooPP: quoteAmount<minQuoteAmount'); TransferHelper.safeApprove(quoteToken, address(feeManager), lpFee); feeManager.collectFee(lpFee, rebateTo); uint256 balanceBefore = IERC20(quoteToken).balanceOf(to); TransferHelper.safeTransfer(quoteToken, to, quoteAmount); require(IERC20(quoteToken).balanceOf(to).sub(balanceBefore) >= minQuoteAmount, 'WooPP: INSUFF_OUTPUT_AMOUNT'); _updateReserve(baseToken, baseInfo, quoteInfo); tokenInfo[baseToken] = baseInfo; tokenInfo[quoteToken] = quoteInfo; emit WooSwap(baseToken, quoteToken, baseAmount, quoteAmount, from, to, rebateTo); } /// @inheritdoc IWooPP function sellQuote( address baseToken, uint256 quoteAmount, uint256 minBaseAmount, address to, address rebateTo ) external override nonReentrant whenNotPaused returns (uint256 baseAmount) { require(baseToken != address(0), 'WooPP: baseToken_ZERO_ADDR'); require(to != address(0), 'WooPP: to_ZERO_ADDR'); require(baseToken != quoteToken, 'WooPP: baseToken==quoteToken'); wooGuardian.checkInputAmount(quoteToken, quoteAmount); address from = msg.sender; TokenInfo memory baseInfo = tokenInfo[baseToken]; require(baseInfo.isValid, 'WooPP: TOKEN_DOES_NOT_EXIST'); TokenInfo memory quoteInfo = tokenInfo[quoteToken]; _autoUpdate(baseToken, baseInfo, quoteInfo); TransferHelper.safeTransferFrom(quoteToken, from, address(this), quoteAmount); uint256 lpFee = quoteAmount.mulCeil(feeManager.feeRate(baseToken)); quoteAmount = quoteAmount.sub(lpFee); baseAmount = getBaseAmountSellQuote(baseToken, quoteAmount, baseInfo, quoteInfo); require(baseAmount >= minBaseAmount, 'WooPP: baseAmount<minBaseAmount'); TransferHelper.safeApprove(quoteToken, address(feeManager), lpFee); feeManager.collectFee(lpFee, rebateTo); wooGuardian.checkSwapAmount(quoteToken, baseToken, quoteAmount, baseAmount); uint256 balanceBefore = IERC20(baseToken).balanceOf(to); TransferHelper.safeTransfer(baseToken, to, baseAmount); require(IERC20(baseToken).balanceOf(to).sub(balanceBefore) >= minBaseAmount, 'WooPP: INSUFF_OUTPUT_AMOUNT'); _updateReserve(baseToken, baseInfo, quoteInfo); tokenInfo[baseToken] = baseInfo; tokenInfo[quoteToken] = quoteInfo; emit WooSwap(quoteToken, baseToken, quoteAmount.add(lpFee), baseAmount, from, to, rebateTo); } /// @dev Set the pairsInfo /// @param newPairsInfo the pairs info to set function setPairsInfo(string calldata newPairsInfo) external nonReentrant onlyStrategist { pairsInfo = newPairsInfo; } /// @dev Get the pool's balance of token /// @param token the token pool to query function poolSize(address token) external view returns (uint256) { return IERC20(token).balanceOf(address(this)); } /// @dev Set wooracle from newWooracle /// @param newWooracle Wooracle address function setWooracle(address newWooracle) external nonReentrant onlyStrategist { require(newWooracle != address(0), 'WooPP: newWooracle_ZERO_ADDR'); wooracle = newWooracle; emit WooracleUpdated(newWooracle); } /// @dev Set wooGuardian from newWooGuardian /// @param newWooGuardian WooGuardian address function setWooGuardian(address newWooGuardian) external nonReentrant onlyStrategist { require(newWooGuardian != address(0), 'WooPP: newWooGuardian_ZERO_ADDR'); wooGuardian = IWooGuardian(newWooGuardian); emit WooGuardianUpdated(newWooGuardian); } /// @dev Set the feeManager. /// @param newFeeManager the fee manager function setFeeManager(address newFeeManager) external nonReentrant onlyStrategist { require(newFeeManager != address(0), 'WooPP: newFeeManager_ZERO_ADDR'); feeManager = IWooFeeManager(newFeeManager); require(feeManager.quoteToken() == quoteToken, 'WooPP: feeManager_quoteToken_INVALID'); emit FeeManagerUpdated(newFeeManager); } /// @dev Add the base token for swap /// @param baseToken the base token /// @param threshold the balance threshold info /// @param R the rebalance refactor function addBaseToken( address baseToken, uint256 threshold, uint256 R ) external nonReentrant onlyStrategist { require(baseToken != address(0), 'WooPP: BASE_TOKEN_ZERO_ADDR'); require(baseToken != quoteToken, 'WooPP: baseToken==quoteToken'); require(threshold <= type(uint112).max, 'WooPP: THRESHOLD_OUT_OF_RANGE'); require(R <= 1e18, 'WooPP: R_OUT_OF_RANGE'); TokenInfo memory info = tokenInfo[baseToken]; require(!info.isValid, 'WooPP: TOKEN_ALREADY_EXISTS'); info.threshold = uint112(threshold); info.R = uint64(R); info.target = max(info.threshold, info.target); info.isValid = true; tokenInfo[baseToken] = info; emit ParametersUpdated(baseToken, threshold, R); } /// @dev Remove the base token /// @param baseToken the base token function removeBaseToken(address baseToken) external nonReentrant onlyStrategist { require(baseToken != address(0), 'WooPP: BASE_TOKEN_ZERO_ADDR'); require(tokenInfo[baseToken].isValid, 'WooPP: TOKEN_DOES_NOT_EXIST'); delete tokenInfo[baseToken]; emit ParametersUpdated(baseToken, 0, 0); } /// @dev Tune the token params /// @param token the token to tune /// @param newThreshold the new balance threshold info /// @param newR the new rebalance refactor function tuneParameters( address token, uint256 newThreshold, uint256 newR ) external nonReentrant onlyStrategist { require(token != address(0), 'WooPP: token_ZERO_ADDR'); require(newThreshold <= type(uint112).max, 'WooPP: THRESHOLD_OUT_OF_RANGE'); require(newR <= 1e18, 'WooPP: R>1'); TokenInfo memory info = tokenInfo[token]; require(info.isValid, 'WooPP: TOKEN_DOES_NOT_EXIST'); info.threshold = uint112(newThreshold); info.R = uint64(newR); info.target = max(info.threshold, info.target); tokenInfo[token] = info; emit ParametersUpdated(token, newThreshold, newR); } /* ----- Admin Functions ----- */ /// @dev Pause the contract. function pause() external onlyStrategist { super._pause(); } /// @dev Restart the contract. function unpause() external onlyStrategist { super._unpause(); } /// @dev Update the strategist info. /// @param strategist the strategist to set /// @param flag true or false function setStrategist(address strategist, bool flag) external nonReentrant onlyStrategist { require(strategist != address(0), 'WooPP: strategist_ZERO_ADDR'); isStrategist[strategist] = flag; emit StrategistUpdated(strategist, flag); } /// @dev Withdraw the token. /// @param token the token to withdraw /// @param to the destination address /// @param amount the amount to withdraw function withdraw( address token, address to, uint256 amount ) public nonReentrant onlyOwner { require(token != address(0), 'WooPP: token_ZERO_ADDR'); require(to != address(0), 'WooPP: to_ZERO_ADDR'); TransferHelper.safeTransfer(token, to, amount); emit Withdraw(token, to, amount); } function withdrawAll(address token, address to) external onlyOwner { withdraw(token, to, IERC20(token).balanceOf(address(this))); } /// @dev Withdraw the token to the OWNER address /// @param token the token function withdrawAllToOwner(address token) external nonReentrant onlyStrategist { require(token != address(0), 'WooPP: token_ZERO_ADDR'); uint256 amount = IERC20(token).balanceOf(address(this)); TransferHelper.safeTransfer(token, _OWNER_, amount); emit Withdraw(token, _OWNER_, amount); } /* ----- Private Functions ----- */ function _autoUpdate( address baseToken, TokenInfo memory baseInfo, TokenInfo memory quoteInfo ) private view { require(baseToken != address(0), 'WooPP: BASETOKEN_ZERO_ADDR'); _updateReserve(baseToken, baseInfo, quoteInfo); // NOTE: only consider the least 32 bigs integer number is good engouh uint32 priceTimestamp = uint32(IWooracle(wooracle).timestamp()); if (priceTimestamp != baseInfo.lastResetTimestamp) { baseInfo.target = max(baseInfo.threshold, baseInfo.reserve); baseInfo.lastResetTimestamp = priceTimestamp; } if (priceTimestamp != quoteInfo.lastResetTimestamp) { quoteInfo.target = max(quoteInfo.threshold, quoteInfo.reserve); quoteInfo.lastResetTimestamp = priceTimestamp; } } function _updateReserve( address baseToken, TokenInfo memory baseInfo, TokenInfo memory quoteInfo ) private view { uint256 baseReserve = IERC20(baseToken).balanceOf(address(this)); uint256 quoteReserve = IERC20(quoteToken).balanceOf(address(this)); require(baseReserve <= type(uint112).max); require(quoteReserve <= type(uint112).max); baseInfo.reserve = uint112(baseReserve); quoteInfo.reserve = uint112(quoteReserve); } // When baseSold >= 0 , users sold the base token function getQuoteAmountLowQuoteSide( uint256 p, uint256 k, uint256 r, uint256 baseAmount ) private pure returns (uint256) { // priceFactor = 1 + k * baseAmount * p * r; uint256 priceFactor = DecimalMath.ONE.add(k.mulCeil(baseAmount).mulCeil(p).mulCeil(r)); // return baseAmount * p / priceFactor; return baseAmount.mulFloor(p).divFloor(priceFactor); // round down } // When baseSold >= 0 function getBaseAmountLowQuoteSide( uint256 p, uint256 k, uint256 r, uint256 quoteAmount ) private pure returns (uint256) { // priceFactor = (1 - k * quoteAmount * r); uint256 priceFactor = DecimalMath.ONE.sub(k.mulFloor(quoteAmount).mulFloor(r)); // return quoteAmount / p / priceFactor; return quoteAmount.divFloor(p).divFloor(priceFactor); } // When quoteSold >= 0 function getBaseAmountLowBaseSide( uint256 p, uint256 k, uint256 r, uint256 quoteAmount ) private pure returns (uint256) { // priceFactor = 1 + k * quoteAmount * r; uint256 priceFactor = DecimalMath.ONE.add(k.mulCeil(quoteAmount).mulCeil(r)); // return quoteAmount / p / priceFactor; return quoteAmount.divFloor(p).divFloor(priceFactor); // round down } // When quoteSold >= 0 function getQuoteAmountLowBaseSide( uint256 p, uint256 k, uint256 r, uint256 baseAmount ) private pure returns (uint256) { // priceFactor = 1 - k * baseAmount * p * r; uint256 priceFactor = DecimalMath.ONE.sub(k.mulFloor(baseAmount).mulFloor(p).mulFloor(r)); // return baseAmount * p / priceFactor; return baseAmount.mulFloor(p).divFloor(priceFactor); // round down } function getBoughtAmount( TokenInfo memory baseInfo, TokenInfo memory quoteInfo, uint256 p, uint256 k, bool isSellBase ) private pure returns (uint256 baseBought, uint256 quoteBought) { uint256 baseSold = 0; if (baseInfo.reserve < baseInfo.target) { baseBought = uint256(baseInfo.target).sub(uint256(baseInfo.reserve)); } else { baseSold = uint256(baseInfo.reserve).sub(uint256(baseInfo.target)); } uint256 quoteSold = 0; if (quoteInfo.reserve < quoteInfo.target) { quoteBought = uint256(quoteInfo.target).sub(uint256(quoteInfo.reserve)); } else { quoteSold = uint256(quoteInfo.reserve).sub(uint256(quoteInfo.target)); } if (baseSold.mulCeil(p) > quoteSold) { baseSold = baseSold.sub(quoteSold.divFloor(p)); quoteSold = 0; } else { quoteSold = quoteSold.sub(baseSold.mulCeil(p)); baseSold = 0; } uint256 virtualBaseBought = getBaseAmountLowBaseSide(p, k, DecimalMath.ONE, quoteSold); if (isSellBase == (virtualBaseBought < baseBought)) { baseBought = virtualBaseBought; } uint256 virtualQuoteBought = getQuoteAmountLowQuoteSide(p, k, DecimalMath.ONE, baseSold); if (isSellBase == (virtualQuoteBought > quoteBought)) { quoteBought = virtualQuoteBought; } } function getQuoteAmountSellBase( address baseToken, uint256 baseAmount, TokenInfo memory baseInfo, TokenInfo memory quoteInfo ) private view returns (uint256 quoteAmount) { uint256 p; uint256 s; uint256 k; bool isFeasible; (p, s, k, isFeasible) = IWooracle(wooracle).state(baseToken); require(isFeasible, 'WooPP: ORACLE_PRICE_NOT_FEASIBLE'); wooGuardian.checkSwapPrice(p, baseToken, quoteToken); // price: p * (1 - s / 2) p = p.mulFloor(DecimalMath.ONE.sub(s.divCeil(DecimalMath.TWO))); uint256 baseBought; uint256 quoteBought; (baseBought, quoteBought) = getBoughtAmount(baseInfo, quoteInfo, p, k, true); if (baseBought > 0) { uint256 quoteSold = getQuoteAmountLowBaseSide(p, k, baseInfo.R, baseBought); if (baseAmount > baseBought) { uint256 newBaseSold = baseAmount.sub(baseBought); quoteAmount = quoteSold.add(getQuoteAmountLowQuoteSide(p, k, DecimalMath.ONE, newBaseSold)); } else { uint256 newBaseBought = baseBought.sub(baseAmount); quoteAmount = quoteSold.sub(getQuoteAmountLowBaseSide(p, k, baseInfo.R, newBaseBought)); } } else { uint256 baseSold = getBaseAmountLowQuoteSide(p, k, DecimalMath.ONE, quoteBought); uint256 newBaseSold = baseAmount.add(baseSold); uint256 newQuoteBought = getQuoteAmountLowQuoteSide(p, k, DecimalMath.ONE, newBaseSold); quoteAmount = newQuoteBought > quoteBought ? newQuoteBought.sub(quoteBought) : 0; } } function getBaseAmountSellQuote( address baseToken, uint256 quoteAmount, TokenInfo memory baseInfo, TokenInfo memory quoteInfo ) private view returns (uint256 baseAmount) { uint256 p; uint256 s; uint256 k; bool isFeasible; (p, s, k, isFeasible) = IWooracle(wooracle).state(baseToken); require(isFeasible, 'WooPP: ORACLE_PRICE_NOT_FEASIBLE'); wooGuardian.checkSwapPrice(p, baseToken, quoteToken); // price: p * (1 + s / 2) p = p.mulCeil(DecimalMath.ONE.add(s.divCeil(DecimalMath.TWO))); uint256 baseBought; uint256 quoteBought; (baseBought, quoteBought) = getBoughtAmount(baseInfo, quoteInfo, p, k, false); if (quoteBought > 0) { uint256 baseSold = getBaseAmountLowQuoteSide(p, k, baseInfo.R, quoteBought); if (quoteAmount > quoteBought) { uint256 newQuoteSold = quoteAmount.sub(quoteBought); baseAmount = baseSold.add(getBaseAmountLowBaseSide(p, k, DecimalMath.ONE, newQuoteSold)); } else { uint256 newQuoteBought = quoteBought.sub(quoteAmount); baseAmount = baseSold.sub(getBaseAmountLowQuoteSide(p, k, baseInfo.R, newQuoteBought)); } } else { uint256 quoteSold = getQuoteAmountLowBaseSide(p, k, DecimalMath.ONE, baseBought); uint256 newQuoteSold = quoteAmount.add(quoteSold); uint256 newBaseBought = getBaseAmountLowBaseSide(p, k, DecimalMath.ONE, newQuoteSold); baseAmount = newBaseBought > baseBought ? newBaseBought.sub(baseBought) : 0; } } function max(uint112 a, uint112 b) private pure returns (uint112) { return a >= b ? a : b; } }
// SPDX-License-Identifier: MIT pragma solidity =0.6.12; pragma experimental ABIEncoderV2; /** * @title Ownable initializable contract. * * @notice Ownership related functions */ contract InitializableOwnable { address public _OWNER_; address public _NEW_OWNER_; bool internal _INITIALIZED_; // ============ Events ============ event OwnershipTransferPrepared(address indexed previousOwner, address indexed newOwner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); // ============ Modifiers ============ modifier notInitialized() { require(!_INITIALIZED_, 'InitializableOwnable: SHOULD_NOT_BE_INITIALIZED'); _; } modifier onlyOwner() { require(msg.sender == _OWNER_, 'InitializableOwnable: NOT_OWNER'); _; } // ============ Functions ============ /// @dev Init _OWNER_ from newOwner and set _INITIALIZED_ as true /// @param newOwner new owner address function initOwner(address newOwner) public notInitialized { _INITIALIZED_ = true; _OWNER_ = newOwner; } /// @dev Set _NEW_OWNER_ from newOwner /// @param newOwner new owner address function transferOwnership(address newOwner) public onlyOwner { emit OwnershipTransferPrepared(_OWNER_, newOwner); _NEW_OWNER_ = newOwner; } /// @dev Set _OWNER_ from _NEW_OWNER_ and set _NEW_OWNER_ equal zero address function claimOwnership() public { require(msg.sender == _NEW_OWNER_, 'InitializableOwnable: INVALID_CLAIM'); emit OwnershipTransferred(_OWNER_, _NEW_OWNER_); _OWNER_ = _NEW_OWNER_; _NEW_OWNER_ = address(0); } }
// SPDX-License-Identifier: MIT pragma solidity =0.6.12; pragma experimental ABIEncoderV2; import '@openzeppelin/contracts/math/SafeMath.sol'; /** * @title DecimalMath * * @notice Functions for fixed point number with 18 decimals */ library DecimalMath { using SafeMath for uint256; uint256 internal constant ONE = 10**18; uint256 internal constant TWO = 2 * 10**18; uint256 internal constant ONE2 = 10**36; function mulFloor(uint256 target, uint256 d) internal pure returns (uint256) { return target.mul(d) / (10**18); } function mulCeil(uint256 target, uint256 d) internal pure returns (uint256) { return _divCeil(target.mul(d), 10**18); } function divFloor(uint256 target, uint256 d) internal pure returns (uint256) { return target.mul(10**18).div(d); } function divCeil(uint256 target, uint256 d) internal pure returns (uint256) { return _divCeil(target.mul(10**18), d); } function reciprocalFloor(uint256 target) internal pure returns (uint256) { return uint256(10**36).div(target); } function reciprocalCeil(uint256 target) internal pure returns (uint256) { return _divCeil(uint256(10**36), target); } function _divCeil(uint256 a, uint256 b) private pure returns (uint256) { uint256 quotient = a.div(b); uint256 remainder = a - quotient * b; if (remainder > 0) { return quotient + 1; } else { return quotient; } } }
// SPDX-License-Identifier: MIT pragma solidity =0.6.12; pragma experimental ABIEncoderV2; /* ░██╗░░░░░░░██╗░█████╗░░█████╗░░░░░░░███████╗██╗ ░██║░░██╗░░██║██╔══██╗██╔══██╗░░░░░░██╔════╝██║ ░╚██╗████╗██╔╝██║░░██║██║░░██║█████╗█████╗░░██║ ░░████╔═████║░██║░░██║██║░░██║╚════╝██╔══╝░░██║ ░░╚██╔╝░╚██╔╝░╚█████╔╝╚█████╔╝░░░░░░██║░░░░░██║ ░░░╚═╝░░░╚═╝░░░╚════╝░░╚════╝░░░░░░░╚═╝░░░░░╚═╝ * * MIT License * =========== * * Copyright (c) 2020 WooTrade * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /// @title The oracle interface by Woo.Network. /// @notice update and posted the latest price info by Woo. interface IWooracle { /// @dev the quote token for Wooracle's pricing. /// @return the quote token function quoteToken() external view returns (address); /// @dev the price for the given base token /// @param base baseToken address /// @return priceNow the current price of base token /// @return feasible whether the current price is feasible and valid function price(address base) external view returns (uint256 priceNow, bool feasible); function getPrice(address base) external view returns (uint256); function getSpread(address base) external view returns (uint256); function getCoeff(address base) external view returns (uint256); /// @dev returns the state for the given base token. /// @param base baseToken address /// @return priceNow the current price of base token /// @return spreadNow the current spread of base token /// @return coeffNow the slippage coefficient of base token /// @return feasible whether the current state is feasible and valid function state(address base) external view returns ( uint256 priceNow, uint256 spreadNow, uint256 coeffNow, bool feasible ); /// @dev returns the last updated timestamp /// @return the last updated timestamp function timestamp() external view returns (uint256); /// @dev returns whether the base token price is valid. /// @param base baseToken address /// @return whether the base token price is valid. function isFeasible(address base) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity =0.6.12; pragma experimental ABIEncoderV2; /* ░██╗░░░░░░░██╗░█████╗░░█████╗░░░░░░░███████╗██╗ ░██║░░██╗░░██║██╔══██╗██╔══██╗░░░░░░██╔════╝██║ ░╚██╗████╗██╔╝██║░░██║██║░░██║█████╗█████╗░░██║ ░░████╔═████║░██║░░██║██║░░██║╚════╝██╔══╝░░██║ ░░╚██╔╝░╚██╔╝░╚█████╔╝╚█████╔╝░░░░░░██║░░░░░██║ ░░░╚═╝░░░╚═╝░░░╚════╝░░╚════╝░░░░░░░╚═╝░░░░░╚═╝ * * MIT License * =========== * * Copyright (c) 2020 WooTrade * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /// @title Woo private pool for swap. /// @notice Use this contract to directly interfact with woo's synthetic proactive /// marketing making pool. /// @author woo.network interface IWooPP { /* ----- Type declarations ----- */ /// @dev struct info to store the token info struct TokenInfo { uint112 reserve; // Token balance uint112 threshold; // Threshold for reserve update uint32 lastResetTimestamp; // Timestamp for last param update uint64 R; // Rebalance coefficient [0, 1] uint112 target; // Targeted balance for pricing bool isValid; // is this token info valid } /* ----- Events ----- */ event StrategistUpdated(address indexed strategist, bool flag); event FeeManagerUpdated(address indexed newFeeManager); event RewardManagerUpdated(address indexed newRewardManager); event WooracleUpdated(address indexed newWooracle); event WooGuardianUpdated(address indexed newWooGuardian); event ParametersUpdated(address indexed baseToken, uint256 newThreshold, uint256 newR); event Withdraw(address indexed token, address indexed to, uint256 amount); event WooSwap( address indexed fromToken, address indexed toToken, uint256 fromAmount, uint256 toAmount, address from, address indexed to, address rebateTo ); /* ----- External Functions ----- */ /// @dev Swap baseToken into quoteToken /// @param baseToken the base token /// @param baseAmount amount of baseToken that user want to swap /// @param minQuoteAmount minimum amount of quoteToken that user accept to receive /// @param to quoteToken receiver address /// @param rebateTo the wallet address for rebate /// @return quoteAmount the swapped amount of quote token function sellBase( address baseToken, uint256 baseAmount, uint256 minQuoteAmount, address to, address rebateTo ) external returns (uint256 quoteAmount); /// @dev Swap quoteToken into baseToken /// @param baseToken the base token /// @param quoteAmount amount of quoteToken that user want to swap /// @param minBaseAmount minimum amount of baseToken that user accept to receive /// @param to baseToken receiver address /// @param rebateTo the wallet address for rebate /// @return baseAmount the swapped amount of base token function sellQuote( address baseToken, uint256 quoteAmount, uint256 minBaseAmount, address to, address rebateTo ) external returns (uint256 baseAmount); /// @dev Query the amount for selling the base token amount. /// @param baseToken the base token to sell /// @param baseAmount the amount to sell /// @return quoteAmount the swapped quote amount function querySellBase(address baseToken, uint256 baseAmount) external view returns (uint256 quoteAmount); /// @dev Query the amount for selling the quote token. /// @param baseToken the base token to receive (buy) /// @param quoteAmount the amount to sell /// @return baseAmount the swapped base token amount function querySellQuote(address baseToken, uint256 quoteAmount) external view returns (uint256 baseAmount); /// @dev get the quote token address /// @return address of quote token function quoteToken() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity =0.6.12; pragma experimental ABIEncoderV2; /* ░██╗░░░░░░░██╗░█████╗░░█████╗░░░░░░░███████╗██╗ ░██║░░██╗░░██║██╔══██╗██╔══██╗░░░░░░██╔════╝██║ ░╚██╗████╗██╔╝██║░░██║██║░░██║█████╗█████╗░░██║ ░░████╔═████║░██║░░██║██║░░██║╚════╝██╔══╝░░██║ ░░╚██╔╝░╚██╔╝░╚█████╔╝╚█████╔╝░░░░░░██║░░░░░██║ ░░░╚═╝░░░╚═╝░░░╚════╝░░╚════╝░░░░░░░╚═╝░░░░░╚═╝ * * MIT License * =========== * * Copyright (c) 2020 WooTrade * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /// @title Contract to collect transaction fee of Woo private pool. interface IWooFeeManager { /* ----- Events ----- */ event FeeRateUpdated(address indexed token, uint256 newFeeRate); event Withdraw(address indexed token, address indexed to, uint256 amount); /* ----- External Functions ----- */ /// @dev fee rate for the given base token: /// NOTE: fee rate decimal 18: 1e16 = 1%, 1e15 = 0.1%, 1e14 = 0.01% /// @param token the base token /// @return the fee rate function feeRate(address token) external view returns (uint256); /// @dev Sets the fee rate for the given token /// @param token the base token /// @param newFeeRate the new fee rate function setFeeRate(address token, uint256 newFeeRate) external; /// @dev Collects the swap fee to the given brokder address. /// @param amount the swap fee amount /// @param brokerAddr the broker address to rebate to function collectFee(uint256 amount, address brokerAddr) external; /// @dev get the quote token address /// @return address of quote token function quoteToken() external view returns (address); /// @dev Collects the fee and distribute to rebate and vault managers. function distributeFees() external; }
// SPDX-License-Identifier: MIT pragma solidity =0.6.12; pragma experimental ABIEncoderV2; /* ░██╗░░░░░░░██╗░█████╗░░█████╗░░░░░░░███████╗██╗ ░██║░░██╗░░██║██╔══██╗██╔══██╗░░░░░░██╔════╝██║ ░╚██╗████╗██╔╝██║░░██║██║░░██║█████╗█████╗░░██║ ░░████╔═████║░██║░░██║██║░░██║╚════╝██╔══╝░░██║ ░░╚██╔╝░╚██╔╝░╚█████╔╝╚█████╔╝░░░░░░██║░░░░░██║ ░░░╚═╝░░░╚═╝░░░╚════╝░░╚════╝░░░░░░░╚═╝░░░░░╚═╝ * * MIT License * =========== * * Copyright (c) 2020 WooTrade * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ import '../interfaces/IWooPP.sol'; /// @title Guardian interface to ensure the trading price and volume correct interface IWooGuardian { event ChainlinkRefOracleUpdated(address indexed token, address indexed chainlinkRefOracle); /* ----- Main check APIs ----- */ function checkSwapPrice( uint256 price, address fromToken, address toToken ) external view; function checkInputAmount(address token, uint256 inputAmount) external view; function checkSwapAmount( address fromToken, address toToken, uint256 fromAmount, uint256 toAmount ) external view; }
// SPDX-License-Identifier: MIT pragma solidity =0.6.12; pragma experimental ABIEncoderV2; interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); /// getRoundData and latestRoundData should both raise "No data present" /// if they do not have data to report, instead of returning unset values /// which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../../utils/Context.sol"; import "./IERC20.sol"; import "../../math/SafeMath.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for {name} and {symbol}, initializes {decimals} with * a default value of 18. * * To select a different value for {decimals}, use {_setupDecimals}. * * All three of these values are immutable: they can only be set once during * construction. */ constructor (string memory name_, string memory symbol_) public { _name = name_; _symbol = symbol_; _decimals = 18; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return _decimals; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Sets {decimals} to a value other than the default one of 18. * * WARNING: This function should only be called from the constructor. Most * applications that interact with token contracts will not expect * {decimals} to ever change, and may work incorrectly if it does. */ function _setupDecimals(uint8 decimals_) internal virtual { _decimals = decimals_; } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./IERC20.sol"; import "../../math/SafeMath.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 SafeMath for uint256; 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' // solhint-disable-next-line max-line-length 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).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () internal { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor () internal { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.6.0; // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::safeApprove: approve failed' ); } function safeTransfer( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::safeTransfer: transfer failed' ); } function safeTransferFrom( address token, address from, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::transferFrom: transferFrom failed' ); } function safeTransferETH(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, 'TransferHelper::safeTransferETH: ETH transfer failed'); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <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 GSN 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 payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (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"); // solhint-disable-next-line avoid-low-level-calls (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"); // solhint-disable-next-line avoid-low-level-calls (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"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
{ "evmVersion": "istanbul", "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"newQuoteToken","type":"address"},{"internalType":"address","name":"newWooracle","type":"address"},{"internalType":"address","name":"newFeeManager","type":"address"},{"internalType":"address","name":"newWooGuardian","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newFeeManager","type":"address"}],"name":"FeeManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferPrepared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"baseToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"newThreshold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newR","type":"uint256"}],"name":"ParametersUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newRewardManager","type":"address"}],"name":"RewardManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"strategist","type":"address"},{"indexed":false,"internalType":"bool","name":"flag","type":"bool"}],"name":"StrategistUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newWooGuardian","type":"address"}],"name":"WooGuardianUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"fromToken","type":"address"},{"indexed":true,"internalType":"address","name":"toToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"rebateTo","type":"address"}],"name":"WooSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newWooracle","type":"address"}],"name":"WooracleUpdated","type":"event"},{"inputs":[],"name":"_NEW_OWNER_","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_OWNER_","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"uint256","name":"threshold","type":"uint256"},{"internalType":"uint256","name":"R","type":"uint256"}],"name":"addBaseToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeManager","outputs":[{"internalType":"contract IWooFeeManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"initOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isStrategist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pairsInfo","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"poolSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"uint256","name":"baseAmount","type":"uint256"}],"name":"querySellBase","outputs":[{"internalType":"uint256","name":"quoteAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"uint256","name":"quoteAmount","type":"uint256"}],"name":"querySellQuote","outputs":[{"internalType":"uint256","name":"baseAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"quoteToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseToken","type":"address"}],"name":"removeBaseToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"uint256","name":"baseAmount","type":"uint256"},{"internalType":"uint256","name":"minQuoteAmount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"rebateTo","type":"address"}],"name":"sellBase","outputs":[{"internalType":"uint256","name":"quoteAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"uint256","name":"quoteAmount","type":"uint256"},{"internalType":"uint256","name":"minBaseAmount","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"rebateTo","type":"address"}],"name":"sellQuote","outputs":[{"internalType":"uint256","name":"baseAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeManager","type":"address"}],"name":"setFeeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newPairsInfo","type":"string"}],"name":"setPairsInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"strategist","type":"address"},{"internalType":"bool","name":"flag","type":"bool"}],"name":"setStrategist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newWooGuardian","type":"address"}],"name":"setWooGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newWooracle","type":"address"}],"name":"setWooracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenInfo","outputs":[{"internalType":"uint112","name":"reserve","type":"uint112"},{"internalType":"uint112","name":"threshold","type":"uint112"},{"internalType":"uint32","name":"lastResetTimestamp","type":"uint32"},{"internalType":"uint64","name":"R","type":"uint64"},{"internalType":"uint112","name":"target","type":"uint112"},{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"newThreshold","type":"uint256"},{"internalType":"uint256","name":"newR","type":"uint256"}],"name":"tuneParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"withdrawAllToOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wooGuardian","outputs":[{"internalType":"contract IWooGuardian","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wooracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b5060405162005321380380620053218339810160408190526200003491620002d4565b60016002556003805460ff191690556001600160a01b038416620000755760405162461bcd60e51b81526004016200006c90620003f1565b60405180910390fd5b6001600160a01b0383166200009e5760405162461bcd60e51b81526004016200006c906200046c565b6001600160a01b038216620000c75760405162461bcd60e51b81526004016200006c9062000334565b6001600160a01b038116620000f05760405162461bcd60e51b81526004016200006c906200036b565b620000fb336200022e565b6001600160601b0319606085901b16608052600680546001600160a01b038581166001600160a01b031992831617909255600880548584169216919091179081905560408051630217a4b760e41b8152905183881693929092169163217a4b7091600480820192602092909190829003018186803b1580156200017d57600080fd5b505afa15801562000192573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b89190620002af565b6001600160a01b031614620001e15760405162461bcd60e51b81526004016200006c9062000428565b600780546001600160a01b039283166001600160a01b0319909116179055929092166000908152600460205260409020600101805460ff60b01b1916600160b01b17905550620004a39050565b600154600160a01b900460ff16156200025b5760405162461bcd60e51b81526004016200006c90620003a2565b6001805460ff60a01b1916600160a01b179055600080546001600160a01b039092166001600160a01b0319909216919091179055565b80516001600160a01b0381168114620002a957600080fd5b92915050565b600060208284031215620002c1578081fd5b620002cd838362000291565b9392505050565b60008060008060808587031215620002ea578283fd5b620002f6868662000291565b935062000307866020870162000291565b925062000318866040870162000291565b915062000329866060870162000291565b905092959194509250565b6020808252601e908201527f576f6f50503a206e65774665654d616e616765725f5a45524f5f414444520000604082015260600190565b6020808252601f908201527f576f6f50503a206e6577576f6f477561726469616e5f5a45524f5f4144445200604082015260600190565b6020808252602f908201527f496e697469616c697a61626c654f776e61626c653a2053484f554c445f4e4f5460408201526e17d09157d253925512505312569151608a1b606082015260800190565b60208082526014908201527f576f6f50503a20494e56414c49445f51554f5445000000000000000000000000604082015260600190565b60208082526024908201527f576f6f50503a206665654d616e616765725f71756f7465546f6b656e5f494e566040820152631053125160e21b606082015260800190565b6020808252601c908201527f576f6f50503a206e6577576f6f7261636c655f5a45524f5f4144445200000000604082015260600190565b60805160601c614dca620005576000398061053852806107e75280610f135280610f8b52806110a1528061122552806113d7528061154a5280611640528061170a52806117b6528061184352806118705280611a645280611bad5280611c7f5280611ded5280611ed75280611fe7528061252e52806128ec52806129645280612a7f5280612b375280612c315280612cec5280612f5b52806130ae52806135e652806139575280613c3a5250614dca6000f3fe608060405234801561001057600080fd5b50600436106101e55760003560e01c80636734faee1161010f578063bec6c1c1116100a2578063f2fde38b11610071578063f2fde38b146103b1578063f3287c2f146103c4578063f5dab711146103d7578063fa75d160146103fc576101e5565b8063bec6c1c114610370578063d0fb020314610383578063d9caed121461038b578063db77c0a11461039e576101e5565b80638456db15116100de5780638456db151461033a578063a1ae849014610342578063bbd1e12214610355578063bc8530f914610368576101e5565b80636734faee146102f95780636846fb501461030c57806379a048761461031f5780638456cb5914610332576101e5565b80633f4ba83a116101875780634e71e0c8116101565780634e71e0c8146102a9578063567b5d6d146102b15780635c975abb146102c457806366410a21146102d9576101e5565b80633f4ba83a14610268578063472d35b91461027057806348d9751e146102835780634c341e1314610296576101e5565b8063217a4b70116101c3578063217a4b7014610230578063301ed02d146102385780633313429d1461024b5780633ef3123614610253576101e5565b806309cae2c8146101ea5780630d009297146101ff57806316048bc414610212575b600080fd5b6101fd6101f836600461418a565b61040f565b005b6101fd61020d366004614152565b6104c7565b61021a610527565b60405161022791906143e8565b60405180910390f35b61021a610536565b6101fd610246366004614152565b61055a565b61021a610639565b61025b610648565b604051610227919061447b565b6101fd6106d6565b6101fd61027e366004614152565b610724565b6101fd610291366004614152565b6108cd565b6101fd6102a4366004614202565b610a4a565b6101fd610b3f565b6101fd6102bf36600461425a565b610bcd565b6102cc610ebb565b6040516102279190614462565b6102ec6102e736600461422f565b610ec4565b6040516102279190614cdc565b6102cc610307366004614152565b611327565b6102ec61031a36600461428e565b61133c565b6102ec61032d36600461422f565b611c30565b6101fd61208b565b61021a6120d7565b6101fd610350366004614152565b6120e6565b6101fd610363366004614152565b6121c5565b61021a612302565b6101fd61037e366004614308565b612311565b61021a612391565b6101fd6103993660046141c2565b6123a0565b6101fd6103ac36600461425a565b61249c565b6101fd6103bf366004614152565b6127cc565b6102ec6103d236600461428e565b612851565b6103ea6103e5366004614152565b61311d565b60405161022796959493929190614c92565b6102ec61040a366004614152565b61317b565b6000546001600160a01b031633146104425760405162461bcd60e51b8152600401610439906148b2565b60405180910390fd5b6104c38282846001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161047391906143e8565b60206040518083038186803b15801561048b57600080fd5b505afa15801561049f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103999190614374565b5050565b600154600160a01b900460ff16156104f15760405162461bcd60e51b815260040161043990614916565b6001805460ff60a01b1916600160a01b179055600080546001600160a01b039092166001600160a01b0319909216919091179055565b6000546001600160a01b031681565b7f000000000000000000000000000000000000000000000000000000000000000081565b60028054141561057c5760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b03163314806105a857503360009081526005602052604090205460ff165b6105c45760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b0381166105ea5760405162461bcd60e51b81526004016104399061471a565b600780546001600160a01b0319166001600160a01b0383169081179091556040517f95543a0f1d7d53325b1264bff29b0cb8704c48f0da6e578463e10a951caf2ebb90600090a2506001600255565b6007546001600160a01b031681565b6009805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156106ce5780601f106106a3576101008083540402835291602001916106ce565b820191906000526020600020905b8154815290600101906020018083116106b157829003601f168201915b505050505081565b6000546001600160a01b03163314806106fe57503360009081526005602052604090205460ff165b61071a5760405162461bcd60e51b8152600401610439906149d2565b610722613200565b565b6002805414156107465760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b031633148061077257503360009081526005602052604090205460ff165b61078e5760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b0381166107b45760405162461bcd60e51b815260040161043990614624565b600880546001600160a01b0319166001600160a01b03838116919091179182905560408051630217a4b760e41b815290517f00000000000000000000000000000000000000000000000000000000000000008316939092169163217a4b7091600480820192602092909190829003018186803b15801561083357600080fd5b505afa158015610847573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086b919061416e565b6001600160a01b0316146108915760405162461bcd60e51b815260040161043990614be0565b6040516001600160a01b038216907fe45f5e140399b0a7e12971ab020724b828fbed8ac408c420884dc7d1bbe506b490600090a2506001600255565b6002805414156108ef5760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b031633148061091b57503360009081526005602052604090205460ff165b6109375760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b03811661095d5760405162461bcd60e51b815260040161043990614a01565b6040516370a0823160e01b81526000906001600160a01b038316906370a082319061098c9030906004016143e8565b60206040518083038186803b1580156109a457600080fd5b505afa1580156109b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109dc9190614374565b6000549091506109f79083906001600160a01b03168361326e565b6000546040516001600160a01b03918216918416907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb90610a39908590614cdc565b60405180910390a350506001600255565b600280541415610a6c5760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b0316331480610a9857503360009081526005602052604090205460ff165b610ab45760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b038216610ada5760405162461bcd60e51b815260040161043990614b72565b6001600160a01b03821660008181526005602052604090819020805460ff1916841515179055517faee0e1c61a3f9668cbb6c91cbe9352a6cbb5334687e9dcf76655d72a23b942ce90610b2e908490614462565b60405180910390a250506001600255565b6001546001600160a01b03163314610b695760405162461bcd60e51b815260040161043990614a31565b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b600280541415610bef5760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b0316331480610c1b57503360009081526005602052604090205460ff165b610c375760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b038316610c5d5760405162461bcd60e51b815260040161043990614a01565b6001600160701b03821115610c845760405162461bcd60e51b8152600401610439906144ef565b670de0b6b3a7640000811115610cac5760405162461bcd60e51b815260040161043990614820565b610cb461408a565b506001600160a01b038316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a08201819052610d5d5760405162461bcd60e51b815260040161043990614aee565b6001600160701b038316602082018190526001600160401b03831660608301526080820151610d8c919061335c565b6001600160701b03908116608083019081526001600160a01b03861660008181526004602090815260409182902086518154928801518489015163ffffffff16600160e01b026001600160e01b03918916600160701b02600160701b600160e01b0319938a166001600160701b031990961695909517929092169390931792909216919091178155606086015160019091018054945160a08801511515600160b01b0260ff60b01b1991909716600160401b02600160401b600160b01b03196001600160401b0390941667ffffffffffffffff19909716969096179290921694909417169390931790915590517f5a1f36141a0cb942bd02bfae3796688b4c89d39ca58a36b286c71492a9b1801290610ea8908690869061446d565b60405180910390a2505060016002555050565b60035460ff1690565b6000610ece610ebb565b15610eeb5760405162461bcd60e51b8152600401610439906147f6565b6001600160a01b038316610f115760405162461bcd60e51b81526004016104399061487b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161415610f635760405162461bcd60e51b815260040161043990614c24565b60075460405163022e0a1160e61b81526001600160a01b0390911690638b82844090610fb5907f0000000000000000000000000000000000000000000000000000000000000000908690600401614449565b60006040518083038186803b158015610fcd57600080fd5b505afa158015610fe1573d6000803e3d6000fd5b50505050610fed61408a565b506001600160a01b038316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a082018190526110965760405162461bcd60e51b815260040161043990614aee565b61109e61408a565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a0820152611154858383613387565b600854604051633409528b60e21b81526000916111e2916001600160a01b039091169063d0254a2c9061118b908a906004016143e8565b60206040518083038186803b1580156111a357600080fd5b505afa1580156111b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111db9190614374565b86906134c5565b90506111ee85826134e2565b94506111fc8686858561350a565b600754604051632ab6f78f60e01b81529195506001600160a01b031690632ab6f78f90611253907f0000000000000000000000000000000000000000000000000000000000000000908a908a908a90600401614420565b60006040518083038186803b15801561126b57600080fd5b505afa15801561127f573d6000803e3d6000fd5b50506040516370a0823160e01b81526001600160a01b03891692506370a0823191506112af9030906004016143e8565b60206040518083038186803b1580156112c757600080fd5b505afa1580156112db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ff9190614374565b84111561131e5760405162461bcd60e51b8152600401610439906149a6565b50505092915050565b60056020526000908152604090205460ff1681565b60006002805414156113605760405162461bcd60e51b815260040161043990614ba9565b6002805561136c610ebb565b156113895760405162461bcd60e51b8152600401610439906147f6565b6001600160a01b0386166113af5760405162461bcd60e51b81526004016104399061487b565b6001600160a01b0383166113d55760405162461bcd60e51b8152600401610439906148e9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b031614156114275760405162461bcd60e51b815260040161043990614c24565b60075460405163022e0a1160e61b81526001600160a01b0390911690638b828440906114599089908990600401614449565b60006040518083038186803b15801561147157600080fd5b505afa158015611485573d6000803e3d6000fd5b50505050600033905061149661408a565b506001600160a01b038716600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a0820181905261153f5760405162461bcd60e51b815260040161043990614aee565b61154761408a565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a08201526115fd898383613387565b6116098984308b61378a565b6116158989848461387b565b600754604051632ab6f78f60e01b81529195506001600160a01b031690632ab6f78f9061166c908c907f0000000000000000000000000000000000000000000000000000000000000000908d908a90600401614420565b60006040518083038186803b15801561168457600080fd5b505afa158015611698573d6000803e3d6000fd5b5050600854604051633409528b60e21b8152600093506116d392506001600160a01b039091169063d0254a2c9061118b908e906004016143e8565b90506116df85826134e2565b9450878510156117015760405162461bcd60e51b8152600401610439906144ae565b600854611739907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b031683613ace565b600854604051633ffbd86960e11b81526001600160a01b0390911690637ff7b0d29061176b9084908a90600401614ce5565b600060405180830381600087803b15801561178557600080fd5b505af1158015611799573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691506370a08231906117ec908b906004016143e8565b60206040518083038186803b15801561180457600080fd5b505afa158015611818573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183c9190614374565b90506118697f0000000000000000000000000000000000000000000000000000000000000000898861326e565b88611910827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a082318c6040518263ffffffff1660e01b81526004016118ba91906143e8565b60206040518083038186803b1580156118d257600080fd5b505afa1580156118e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190a9190614374565b906134e2565b101561192e5760405162461bcd60e51b815260040161043990614844565b6119398b8585613bb5565b83600460008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160701b0302191690836001600160701b03160217905550602082015181600001600e6101000a8154816001600160701b0302191690836001600160701b03160217905550604082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160006101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160010160086101000a8154816001600160701b0302191690836001600160701b0316021790555060a08201518160010160166101000a81548160ff02191690831515021790555090505082600460007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160701b0302191690836001600160701b03160217905550602082015181600001600e6101000a8154816001600160701b0302191690836001600160701b03160217905550604082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160006101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160010160086101000a8154816001600160701b0302191690836001600160701b0316021790555060a08201518160010160166101000a81548160ff021916908315150217905550905050876001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168c6001600160a01b03167f74ef34e2ea7c5d9f7b7ed44e97ad44b4303416c3a660c3fb5b3bdb95a1d6abd38d8a8a8d604051611c149493929190614d1b565b60405180910390a4505060016002555091979650505050505050565b6000611c3a610ebb565b15611c575760405162461bcd60e51b8152600401610439906147f6565b6001600160a01b038316611c7d5760405162461bcd60e51b81526004016104399061487b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03161415611ccf5760405162461bcd60e51b815260040161043990614c24565b60075460405163022e0a1160e61b81526001600160a01b0390911690638b82844090611d019086908690600401614449565b60006040518083038186803b158015611d1957600080fd5b505afa158015611d2d573d6000803e3d6000fd5b50505050611d3961408a565b506001600160a01b038316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a08201819052611de25760405162461bcd60e51b815260040161043990614aee565b611dea61408a565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a0820152611ea0858383613387565b611eac8585848461387b565b600754604051632ab6f78f60e01b81529194506001600160a01b031690632ab6f78f90611f039088907f00000000000000000000000000000000000000000000000000000000000000009089908990600401614420565b60006040518083038186803b158015611f1b57600080fd5b505afa158015611f2f573d6000803e3d6000fd5b5050600854604051633409528b60e21b815260009350611fc192506001600160a01b039091169063d0254a2c90611f6a908a906004016143e8565b60206040518083038186803b158015611f8257600080fd5b505afa158015611f96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fba9190614374565b85906134c5565b9050611fcd84826134e2565b6040516370a0823160e01b81529094506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a082319061201c9030906004016143e8565b60206040518083038186803b15801561203457600080fd5b505afa158015612048573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206c9190614374565b84111561131e5760405162461bcd60e51b8152600401610439906145c0565b6000546001600160a01b03163314806120b357503360009081526005602052604090205460ff165b6120cf5760405162461bcd60e51b8152600401610439906149d2565b610722613d15565b6001546001600160a01b031681565b6002805414156121085760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b031633148061213457503360009081526005602052604090205460ff165b6121505760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b0381166121765760405162461bcd60e51b815260040161043990614c5b565b600680546001600160a01b0319166001600160a01b0383169081179091556040517f59ddfdd1bf7e3ea08a07e8aaa1fe2ce9c840fab69fe5ede6ea727a45eb42fc6690600090a2506001600255565b6002805414156121e75760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b031633148061221357503360009081526005602052604090205460ff165b61222f5760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b0381166122555760405162461bcd60e51b81526004016104399061465b565b6001600160a01b038116600090815260046020526040902060010154600160b01b900460ff166122975760405162461bcd60e51b815260040161043990614aee565b6001600160a01b03811660008181526004602052604080822082815560010180546001600160b81b0319169055517f5a1f36141a0cb942bd02bfae3796688b4c89d39ca58a36b286c71492a9b18012916122f291819061446d565b60405180910390a2506001600255565b6006546001600160a01b031681565b6002805414156123335760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b031633148061235f57503360009081526005602052604090205460ff165b61237b5760405162461bcd60e51b8152600401610439906149d2565b612387600983836140bf565b5050600160025550565b6008546001600160a01b031681565b6002805414156123c25760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b031633146123f05760405162461bcd60e51b8152600401610439906148b2565b6001600160a01b0383166124165760405162461bcd60e51b815260040161043990614a01565b6001600160a01b03821661243c5760405162461bcd60e51b8152600401610439906148e9565b61244783838361326e565b816001600160a01b0316836001600160a01b03167f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb8360405161248a9190614cdc565b60405180910390a35050600160025550565b6002805414156124be5760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b03163314806124ea57503360009081526005602052604090205460ff165b6125065760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b03831661252c5760405162461bcd60e51b81526004016104399061465b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316141561257e5760405162461bcd60e51b815260040161043990614c24565b6001600160701b038211156125a55760405162461bcd60e51b8152600401610439906144ef565b670de0b6b3a76400008111156125cd5760405162461bcd60e51b815260040161043990614abf565b6125d561408a565b506001600160a01b038316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff1615801560a083015261267d5760405162461bcd60e51b8152600401610439906147bf565b6001600160701b038316602082018190526001600160401b038316606083015260808201516126ac919061335c565b6001600160701b0390811660808301908152600160a084018181526001600160a01b03881660008181526004602090815260409182902088518154928a0151848b015163ffffffff16600160e01b026001600160e01b03918b16600160701b02600160701b600160e01b0319938c166001600160701b031990961695909517929092169390931792909216919091178155606088015194018054955193511515600160b01b0260ff60b01b1994909716600160401b02600160401b600160b01b03196001600160401b0390961667ffffffffffffffff1990971696909617949094169490941791909116939093179055517f5a1f36141a0cb942bd02bfae3796688b4c89d39ca58a36b286c71492a9b1801290610ea8908690869061446d565b6000546001600160a01b031633146127f65760405162461bcd60e51b8152600401610439906148b2565b600080546040516001600160a01b03808516939216917fdcf55418cee3220104fef63f979ff3c4097ad240c0c43dcb33ce837748983e6291a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b60006002805414156128755760405162461bcd60e51b815260040161043990614ba9565b60028055612881610ebb565b1561289e5760405162461bcd60e51b8152600401610439906147f6565b6001600160a01b0386166128c45760405162461bcd60e51b81526004016104399061487b565b6001600160a01b0383166128ea5760405162461bcd60e51b8152600401610439906148e9565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b0316141561293c5760405162461bcd60e51b815260040161043990614c24565b60075460405163022e0a1160e61b81526001600160a01b0390911690638b8284409061298e907f0000000000000000000000000000000000000000000000000000000000000000908990600401614449565b60006040518083038186803b1580156129a657600080fd5b505afa1580156129ba573d6000803e3d6000fd5b5050505060003390506129cb61408a565b506001600160a01b038716600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a08201819052612a745760405162461bcd60e51b815260040161043990614aee565b612a7c61408a565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a0820152612b32898383613387565b612b5e7f000000000000000000000000000000000000000000000000000000000000000084308b61378a565b600854604051633409528b60e21b8152600091612bec916001600160a01b039091169063d0254a2c90612b95908e906004016143e8565b60206040518083038186803b158015612bad57600080fd5b505afa158015612bc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be59190614374565b8a906134c5565b9050612bf889826134e2565b9850612c068a8a858561350a565b945087851015612c285760405162461bcd60e51b815260040161043990614788565b600854612c60907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b031683613ace565b600854604051633ffbd86960e11b81526001600160a01b0390911690637ff7b0d290612c929084908a90600401614ce5565b600060405180830381600087803b158015612cac57600080fd5b505af1158015612cc0573d6000803e3d6000fd5b5050600754604051632ab6f78f60e01b81526001600160a01b039091169250632ab6f78f9150612d1a907f0000000000000000000000000000000000000000000000000000000000000000908e908e908b90600401614420565b60006040518083038186803b158015612d3257600080fd5b505afa158015612d46573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506001600160a01b038d1691506370a0823190612d79908b906004016143e8565b60206040518083038186803b158015612d9157600080fd5b505afa158015612da5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dc99190614374565b9050612dd68b898861326e565b88612e07828d6001600160a01b03166370a082318c6040518263ffffffff1660e01b81526004016118ba91906143e8565b1015612e255760405162461bcd60e51b815260040161043990614844565b612e308b8585613bb5565b83600460008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160701b0302191690836001600160701b03160217905550602082015181600001600e6101000a8154816001600160701b0302191690836001600160701b03160217905550604082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160006101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160010160086101000a8154816001600160701b0302191690836001600160701b0316021790555060a08201518160010160166101000a81548160ff02191690831515021790555090505082600460007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160701b0302191690836001600160701b03160217905550602082015181600001600e6101000a8154816001600160701b0302191690836001600160701b03160217905550604082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160006101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160010160086101000a8154816001600160701b0302191690836001600160701b0316021790555060a08201518160010160166101000a81548160ff021916908315150217905550905050876001600160a01b03168b6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f74ef34e2ea7c5d9f7b7ed44e97ad44b4303416c3a660c3fb5b3bdb95a1d6abd361310a868f613d7090919063ffffffff16565b8a8a8d604051611c149493929190614d1b565b600460205260009081526040902080546001909101546001600160701b0380831692600160701b8104821692600160e01b90910463ffffffff16916001600160401b03821691600160401b810490911690600160b01b900460ff1686565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906131aa9030906004016143e8565b60206040518083038186803b1580156131c257600080fd5b505afa1580156131d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131fa9190614374565b92915050565b613208610ebb565b6132245760405162461bcd60e51b81526004016104399061455b565b6003805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa613257613d95565b60405161326491906143e8565b60405180910390a1565b60006060846001600160a01b031663a9059cbb8585604051602401613294929190614449565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516132cd91906143cc565b6000604051808303816000865af19150503d806000811461330a576040519150601f19603f3d011682016040523d82523d6000602084013e61330f565b606091505b509150915081801561333957508051158061333957508080602001905181019061333991906142ec565b6133555760405162461bcd60e51b815260040161043990614b25565b5050505050565b6000816001600160701b0316836001600160701b0316101561337e5781613380565b825b9392505050565b6001600160a01b0383166133ad5760405162461bcd60e51b815260040161043990614589565b6133b8838383613bb5565b60065460408051635c03bbf560e11b815290516000926001600160a01b03169163b80777ea916004808301926020929190829003018186803b1580156133fd57600080fd5b505afa158015613411573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134359190614374565b9050826040015163ffffffff168163ffffffff161461347b576134608360200151846000015161335c565b6001600160701b0316608084015263ffffffff811660408401525b816040015163ffffffff168163ffffffff16146134bf576134a48260200151836000015161335c565b6001600160701b0316608083015263ffffffff811660408301525b50505050565b60006133806134d48484613d99565b670de0b6b3a7640000613dd3565b6000828211156135045760405162461bcd60e51b8152600401610439906146e3565b50900390565b6006546040516331e658a560e01b815260009182918291829182916001600160a01b0316906331e658a590613543908c906004016143e8565b60806040518083038186803b15801561355b57600080fd5b505afa15801561356f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613593919061438c565b92965090945092509050806135ba5760405162461bcd60e51b815260040161043990614526565b60075460405163927e40cf60e01b81526001600160a01b039091169063927e40cf9061360e9087908d907f000000000000000000000000000000000000000000000000000000000000000090600401614cfc565b60006040518083038186803b15801561362657600080fd5b505afa15801561363a573d6000803e3d6000fd5b5050505061366e611fba61365f671bc16d674ec8000086613e0090919063ffffffff16565b670de0b6b3a764000090613d70565b9350600080613681898988876000613e1d565b909250905080156137205760006136a787868c606001516001600160401b031685613f92565b9050818b11156136e55760006136bd8c846134e2565b90506136dd6136d68988670de0b6b3a764000085613fcc565b8390613d70565b98505061371a565b60006136f1838d6134e2565b905061371661370f89888e606001516001600160401b031685613f92565b83906134e2565b9850505b5061377c565b60006137368786670de0b6b3a764000086613fe6565b905060006137448c83613d70565b9050600061375c8988670de0b6b3a764000085613fcc565b905084811161376c576000613776565b61377681866134e2565b99505050505b505050505050949350505050565b60006060856001600160a01b03166323b872dd8686866040516024016137b2939291906143fc565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516137eb91906143cc565b6000604051808303816000865af19150503d8060008114613828576040519150601f19603f3d011682016040523d82523d6000602084013e61382d565b606091505b509150915081801561385757508051158061385757508080602001905181019061385791906142ec565b6138735760405162461bcd60e51b815260040161043990614692565b505050505050565b6006546040516331e658a560e01b815260009182918291829182916001600160a01b0316906331e658a5906138b4908c906004016143e8565b60806040518083038186803b1580156138cc57600080fd5b505afa1580156138e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613904919061438c565b929650909450925090508061392b5760405162461bcd60e51b815260040161043990614526565b60075460405163927e40cf60e01b81526001600160a01b039091169063927e40cf9061397f9087908d907f000000000000000000000000000000000000000000000000000000000000000090600401614cfc565b60006040518083038186803b15801561399757600080fd5b505afa1580156139ab573d6000803e3d6000fd5b505050506139e66139df6139d0671bc16d674ec8000086613e0090919063ffffffff16565b670de0b6b3a7640000906134e2565b8590614008565b93506000806139f9898988876001613e1d565b90925090508115613a78576000613a1f87868c606001516001600160401b031686613fe6565b9050828b1115613a4e576000613a358c856134e2565b90506136dd6136d68988670de0b6b3a76400008561402c565b6000613a5a848d6134e2565b905061371661370f89888e606001516001600160401b031685613fe6565b6000613a8e8786670de0b6b3a764000085613f92565b90506000613a9c8c83613d70565b90506000613ab48988670de0b6b3a76400008561402c565b9050838111613ac4576000613776565b61377681856134e2565b60006060846001600160a01b031663095ea7b38585604051602401613af4929190614449565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051613b2d91906143cc565b6000604051808303816000865af19150503d8060008114613b6a576040519150601f19603f3d011682016040523d82523d6000602084013e613b6f565b606091505b5091509150818015613b99575080511580613b99575080806020019051810190613b9991906142ec565b6133555760405162461bcd60e51b815260040161043990614a74565b6040516370a0823160e01b81526000906001600160a01b038516906370a0823190613be49030906004016143e8565b60206040518083038186803b158015613bfc57600080fd5b505afa158015613c10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c349190614374565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401613c8491906143e8565b60206040518083038186803b158015613c9c57600080fd5b505afa158015613cb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cd49190614374565b90506001600160701b03821115613cea57600080fd5b6001600160701b03811115613cfe57600080fd5b6001600160701b0391821690935291909116905250565b613d1d610ebb565b15613d3a5760405162461bcd60e51b8152600401610439906147f6565b6003805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613257613d95565b6000828201838110156133805760405162461bcd60e51b8152600401610439906145ed565b3390565b600082613da8575060006131fa565b82820282848281613db557fe5b04146133805760405162461bcd60e51b815260040161043990614965565b600080613de08484614042565b905082810284038015613df8575060010190506131fa565b5090506131fa565b6000613380613e1784670de0b6b3a7640000613d99565b83613dd3565b600080600087608001516001600160701b031688600001516001600160701b03161015613e685787516080890151613e61916001600160701b0391821691166134e2565b9250613e88565b60808801518851613e85916001600160701b0391821691166134e2565b90505b600087608001516001600160701b031688600001516001600160701b03161015613ed05787516080890151613ec9916001600160701b0391821691166134e2565b9250613ef0565b60808801518851613eed916001600160701b0391821691166134e2565b90505b80613efb83896134c5565b1115613f1957613f0e61370f828961406c565b915060009050613f34565b613f2d613f2683896134c5565b82906134e2565b9050600091505b6000613f4a8888670de0b6b3a764000085613fcc565b90508515158582101415613f5c578094505b6000613f728989670de0b6b3a76400008761402c565b90508615158582111415613f84578094505b505050509550959350505050565b600080613fac6139d085613fa68887614008565b90614008565b9050613fc281613fbc858961406c565b9061406c565b9695505050505050565b600080613fac61365f85613fe088876134c5565b906134c5565b600080613ffc6139d085613fa689818a89614008565b9050613fc281613fbc85895b6000670de0b6b3a764000061401d8484613d99565b8161402457fe5b049392505050565b600080613ffc61365f85613fe089818a896134c5565b60008082116140635760405162461bcd60e51b815260040161043990614751565b81838161402457fe5b60006133808261408485670de0b6b3a7640000613d99565b90614042565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106141005782800160ff1982351617855561412d565b8280016001018555821561412d579182015b8281111561412d578235825591602001919060010190614112565b5061413992915061413d565b5090565b5b80821115614139576000815560010161413e565b600060208284031215614163578081fd5b813561338081614d6e565b60006020828403121561417f578081fd5b815161338081614d6e565b6000806040838503121561419c578081fd5b82356141a781614d6e565b915060208301356141b781614d6e565b809150509250929050565b6000806000606084860312156141d6578081fd5b83356141e181614d6e565b925060208401356141f181614d6e565b929592945050506040919091013590565b60008060408385031215614214578182fd5b823561421f81614d6e565b915060208301356141b781614d86565b60008060408385031215614241578182fd5b823561424c81614d6e565b946020939093013593505050565b60008060006060848603121561426e578283fd5b833561427981614d6e565b95602085013595506040909401359392505050565b600080600080600060a086880312156142a5578081fd5b85356142b081614d6e565b9450602086013593506040860135925060608601356142ce81614d6e565b915060808601356142de81614d6e565b809150509295509295909350565b6000602082840312156142fd578081fd5b815161338081614d86565b6000806020838503121561431a578182fd5b82356001600160401b0380821115614330578384fd5b818501915085601f830112614343578384fd5b813581811115614351578485fd5b866020828501011115614362578485fd5b60209290920196919550909350505050565b600060208284031215614385578081fd5b5051919050565b600080600080608085870312156143a1578384fd5b84519350602085015192506040850151915060608501516143c181614d86565b939692955090935050565b600082516143de818460208701614d42565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b918252602082015260400190565b600060208252825180602084015261449a816040850160208701614d42565b601f01601f19169190910160400192915050565b60208082526021908201527f576f6f50503a2071756f7465416d6f756e743c6d696e51756f7465416d6f756e6040820152601d60fa1b606082015260800190565b6020808252601d908201527f576f6f50503a205448524553484f4c445f4f55545f4f465f52414e4745000000604082015260600190565b6020808252818101527f576f6f50503a204f5241434c455f50524943455f4e4f545f4645415349424c45604082015260600190565b60208082526014908201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604082015260600190565b6020808252601a908201527f576f6f50503a2042415345544f4b454e5f5a45524f5f41444452000000000000604082015260600190565b602080825260139082015272576f6f50503a20494e535546465f51554f544560681b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601e908201527f576f6f50503a206e65774665654d616e616765725f5a45524f5f414444520000604082015260600190565b6020808252601b908201527f576f6f50503a20424153455f544f4b454e5f5a45524f5f414444520000000000604082015260600190565b60208082526031908201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a207472604082015270185b9cd9995c919c9bdb4819985a5b1959607a1b606082015260800190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252601f908201527f576f6f50503a206e6577576f6f477561726469616e5f5a45524f5f4144445200604082015260600190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252601f908201527f576f6f50503a2062617365416d6f756e743c6d696e42617365416d6f756e7400604082015260600190565b6020808252601b908201527f576f6f50503a20544f4b454e5f414c52454144595f4558495354530000000000604082015260600190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252600a9082015269576f6f50503a20523e3160b01b604082015260600190565b6020808252601b908201527f576f6f50503a20494e535546465f4f55545055545f414d4f554e540000000000604082015260600190565b6020808252601a908201527f576f6f50503a2062617365546f6b656e5f5a45524f5f41444452000000000000604082015260600190565b6020808252601f908201527f496e697469616c697a61626c654f776e61626c653a204e4f545f4f574e455200604082015260600190565b6020808252601390820152722bb7b7a8281d103a37afad22a927afa0a2222960691b604082015260600190565b6020808252602f908201527f496e697469616c697a61626c654f776e61626c653a2053484f554c445f4e4f5460408201526e17d09157d253925512505312569151608a1b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260129082015271576f6f50503a20494e535546465f4241534560701b604082015260600190565b60208082526015908201527415dbdbd4140e881393d517d4d51490551151d254d5605a1b604082015260600190565b6020808252601690820152752bb7b7a8281d103a37b5b2b72fad22a927afa0a2222960511b604082015260600190565b60208082526023908201527f496e697469616c697a61626c654f776e61626c653a20494e56414c49445f434c60408201526241494d60e81b606082015260800190565b6020808252602b908201527f5472616e7366657248656c7065723a3a73616665417070726f76653a2061707060408201526a1c9bdd994819985a5b195960aa1b606082015260800190565b602080825260159082015274576f6f50503a20525f4f55545f4f465f52414e474560581b604082015260600190565b6020808252601b908201527f576f6f50503a20544f4b454e5f444f45535f4e4f545f45584953540000000000604082015260600190565b6020808252602d908201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260408201526c185b9cd9995c8819985a5b1959609a1b606082015260800190565b6020808252601b908201527f576f6f50503a20737472617465676973745f5a45524f5f414444520000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526024908201527f576f6f50503a206665654d616e616765725f71756f7465546f6b656e5f494e566040820152631053125160e21b606082015260800190565b6020808252601c908201527f576f6f50503a2062617365546f6b656e3d3d71756f7465546f6b656e00000000604082015260600190565b6020808252601c908201527f576f6f50503a206e6577576f6f7261636c655f5a45524f5f4144445200000000604082015260600190565b6001600160701b039687168152948616602086015263ffffffff9390931660408501526001600160401b03919091166060840152909216608082015290151560a082015260c00190565b90815260200190565b9182526001600160a01b0316602082015260400190565b9283526001600160a01b03918216602084015216604082015260600190565b93845260208401929092526001600160a01b03908116604084015216606082015260800190565b60005b83811015614d5d578181015183820152602001614d45565b838111156134bf5750506000910152565b6001600160a01b0381168114614d8357600080fd5b50565b8015158114614d8357600080fdfea2646970667358221220f2993ee346cef41e5368bcfebfdea754da2f33828e2079ef1ec0afb35997e99764736f6c634300060c003300000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75000000000000000000000000209102c0d2e34282494114ea76d5251c8e7ea7ab000000000000000000000000be1a0fcccfa9c9065152b7770b918f7c59914e8d000000000000000000000000128758d0e909624841ab29d53919646bfbda5db2
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101e55760003560e01c80636734faee1161010f578063bec6c1c1116100a2578063f2fde38b11610071578063f2fde38b146103b1578063f3287c2f146103c4578063f5dab711146103d7578063fa75d160146103fc576101e5565b8063bec6c1c114610370578063d0fb020314610383578063d9caed121461038b578063db77c0a11461039e576101e5565b80638456db15116100de5780638456db151461033a578063a1ae849014610342578063bbd1e12214610355578063bc8530f914610368576101e5565b80636734faee146102f95780636846fb501461030c57806379a048761461031f5780638456cb5914610332576101e5565b80633f4ba83a116101875780634e71e0c8116101565780634e71e0c8146102a9578063567b5d6d146102b15780635c975abb146102c457806366410a21146102d9576101e5565b80633f4ba83a14610268578063472d35b91461027057806348d9751e146102835780634c341e1314610296576101e5565b8063217a4b70116101c3578063217a4b7014610230578063301ed02d146102385780633313429d1461024b5780633ef3123614610253576101e5565b806309cae2c8146101ea5780630d009297146101ff57806316048bc414610212575b600080fd5b6101fd6101f836600461418a565b61040f565b005b6101fd61020d366004614152565b6104c7565b61021a610527565b60405161022791906143e8565b60405180910390f35b61021a610536565b6101fd610246366004614152565b61055a565b61021a610639565b61025b610648565b604051610227919061447b565b6101fd6106d6565b6101fd61027e366004614152565b610724565b6101fd610291366004614152565b6108cd565b6101fd6102a4366004614202565b610a4a565b6101fd610b3f565b6101fd6102bf36600461425a565b610bcd565b6102cc610ebb565b6040516102279190614462565b6102ec6102e736600461422f565b610ec4565b6040516102279190614cdc565b6102cc610307366004614152565b611327565b6102ec61031a36600461428e565b61133c565b6102ec61032d36600461422f565b611c30565b6101fd61208b565b61021a6120d7565b6101fd610350366004614152565b6120e6565b6101fd610363366004614152565b6121c5565b61021a612302565b6101fd61037e366004614308565b612311565b61021a612391565b6101fd6103993660046141c2565b6123a0565b6101fd6103ac36600461425a565b61249c565b6101fd6103bf366004614152565b6127cc565b6102ec6103d236600461428e565b612851565b6103ea6103e5366004614152565b61311d565b60405161022796959493929190614c92565b6102ec61040a366004614152565b61317b565b6000546001600160a01b031633146104425760405162461bcd60e51b8152600401610439906148b2565b60405180910390fd5b6104c38282846001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161047391906143e8565b60206040518083038186803b15801561048b57600080fd5b505afa15801561049f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103999190614374565b5050565b600154600160a01b900460ff16156104f15760405162461bcd60e51b815260040161043990614916565b6001805460ff60a01b1916600160a01b179055600080546001600160a01b039092166001600160a01b0319909216919091179055565b6000546001600160a01b031681565b7f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b7581565b60028054141561057c5760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b03163314806105a857503360009081526005602052604090205460ff165b6105c45760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b0381166105ea5760405162461bcd60e51b81526004016104399061471a565b600780546001600160a01b0319166001600160a01b0383169081179091556040517f95543a0f1d7d53325b1264bff29b0cb8704c48f0da6e578463e10a951caf2ebb90600090a2506001600255565b6007546001600160a01b031681565b6009805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156106ce5780601f106106a3576101008083540402835291602001916106ce565b820191906000526020600020905b8154815290600101906020018083116106b157829003601f168201915b505050505081565b6000546001600160a01b03163314806106fe57503360009081526005602052604090205460ff165b61071a5760405162461bcd60e51b8152600401610439906149d2565b610722613200565b565b6002805414156107465760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b031633148061077257503360009081526005602052604090205460ff165b61078e5760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b0381166107b45760405162461bcd60e51b815260040161043990614624565b600880546001600160a01b0319166001600160a01b03838116919091179182905560408051630217a4b760e41b815290517f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b758316939092169163217a4b7091600480820192602092909190829003018186803b15801561083357600080fd5b505afa158015610847573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086b919061416e565b6001600160a01b0316146108915760405162461bcd60e51b815260040161043990614be0565b6040516001600160a01b038216907fe45f5e140399b0a7e12971ab020724b828fbed8ac408c420884dc7d1bbe506b490600090a2506001600255565b6002805414156108ef5760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b031633148061091b57503360009081526005602052604090205460ff165b6109375760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b03811661095d5760405162461bcd60e51b815260040161043990614a01565b6040516370a0823160e01b81526000906001600160a01b038316906370a082319061098c9030906004016143e8565b60206040518083038186803b1580156109a457600080fd5b505afa1580156109b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109dc9190614374565b6000549091506109f79083906001600160a01b03168361326e565b6000546040516001600160a01b03918216918416907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb90610a39908590614cdc565b60405180910390a350506001600255565b600280541415610a6c5760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b0316331480610a9857503360009081526005602052604090205460ff165b610ab45760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b038216610ada5760405162461bcd60e51b815260040161043990614b72565b6001600160a01b03821660008181526005602052604090819020805460ff1916841515179055517faee0e1c61a3f9668cbb6c91cbe9352a6cbb5334687e9dcf76655d72a23b942ce90610b2e908490614462565b60405180910390a250506001600255565b6001546001600160a01b03163314610b695760405162461bcd60e51b815260040161043990614a31565b600154600080546040516001600160a01b0393841693909116917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a360018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b600280541415610bef5760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b0316331480610c1b57503360009081526005602052604090205460ff165b610c375760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b038316610c5d5760405162461bcd60e51b815260040161043990614a01565b6001600160701b03821115610c845760405162461bcd60e51b8152600401610439906144ef565b670de0b6b3a7640000811115610cac5760405162461bcd60e51b815260040161043990614820565b610cb461408a565b506001600160a01b038316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a08201819052610d5d5760405162461bcd60e51b815260040161043990614aee565b6001600160701b038316602082018190526001600160401b03831660608301526080820151610d8c919061335c565b6001600160701b03908116608083019081526001600160a01b03861660008181526004602090815260409182902086518154928801518489015163ffffffff16600160e01b026001600160e01b03918916600160701b02600160701b600160e01b0319938a166001600160701b031990961695909517929092169390931792909216919091178155606086015160019091018054945160a08801511515600160b01b0260ff60b01b1991909716600160401b02600160401b600160b01b03196001600160401b0390941667ffffffffffffffff19909716969096179290921694909417169390931790915590517f5a1f36141a0cb942bd02bfae3796688b4c89d39ca58a36b286c71492a9b1801290610ea8908690869061446d565b60405180910390a2505060016002555050565b60035460ff1690565b6000610ece610ebb565b15610eeb5760405162461bcd60e51b8152600401610439906147f6565b6001600160a01b038316610f115760405162461bcd60e51b81526004016104399061487b565b7f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b0316836001600160a01b03161415610f635760405162461bcd60e51b815260040161043990614c24565b60075460405163022e0a1160e61b81526001600160a01b0390911690638b82844090610fb5907f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75908690600401614449565b60006040518083038186803b158015610fcd57600080fd5b505afa158015610fe1573d6000803e3d6000fd5b50505050610fed61408a565b506001600160a01b038316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a082018190526110965760405162461bcd60e51b815260040161043990614aee565b61109e61408a565b507f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b0316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a0820152611154858383613387565b600854604051633409528b60e21b81526000916111e2916001600160a01b039091169063d0254a2c9061118b908a906004016143e8565b60206040518083038186803b1580156111a357600080fd5b505afa1580156111b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111db9190614374565b86906134c5565b90506111ee85826134e2565b94506111fc8686858561350a565b600754604051632ab6f78f60e01b81529195506001600160a01b031690632ab6f78f90611253907f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75908a908a908a90600401614420565b60006040518083038186803b15801561126b57600080fd5b505afa15801561127f573d6000803e3d6000fd5b50506040516370a0823160e01b81526001600160a01b03891692506370a0823191506112af9030906004016143e8565b60206040518083038186803b1580156112c757600080fd5b505afa1580156112db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ff9190614374565b84111561131e5760405162461bcd60e51b8152600401610439906149a6565b50505092915050565b60056020526000908152604090205460ff1681565b60006002805414156113605760405162461bcd60e51b815260040161043990614ba9565b6002805561136c610ebb565b156113895760405162461bcd60e51b8152600401610439906147f6565b6001600160a01b0386166113af5760405162461bcd60e51b81526004016104399061487b565b6001600160a01b0383166113d55760405162461bcd60e51b8152600401610439906148e9565b7f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b0316866001600160a01b031614156114275760405162461bcd60e51b815260040161043990614c24565b60075460405163022e0a1160e61b81526001600160a01b0390911690638b828440906114599089908990600401614449565b60006040518083038186803b15801561147157600080fd5b505afa158015611485573d6000803e3d6000fd5b50505050600033905061149661408a565b506001600160a01b038716600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a0820181905261153f5760405162461bcd60e51b815260040161043990614aee565b61154761408a565b507f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b0316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a08201526115fd898383613387565b6116098984308b61378a565b6116158989848461387b565b600754604051632ab6f78f60e01b81529195506001600160a01b031690632ab6f78f9061166c908c907f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75908d908a90600401614420565b60006040518083038186803b15801561168457600080fd5b505afa158015611698573d6000803e3d6000fd5b5050600854604051633409528b60e21b8152600093506116d392506001600160a01b039091169063d0254a2c9061118b908e906004016143e8565b90506116df85826134e2565b9450878510156117015760405162461bcd60e51b8152600401610439906144ae565b600854611739907f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75906001600160a01b031683613ace565b600854604051633ffbd86960e11b81526001600160a01b0390911690637ff7b0d29061176b9084908a90600401614ce5565b600060405180830381600087803b15801561178557600080fd5b505af1158015611799573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506001600160a01b037f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b751691506370a08231906117ec908b906004016143e8565b60206040518083038186803b15801561180457600080fd5b505afa158015611818573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183c9190614374565b90506118697f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75898861326e565b88611910827f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b03166370a082318c6040518263ffffffff1660e01b81526004016118ba91906143e8565b60206040518083038186803b1580156118d257600080fd5b505afa1580156118e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190a9190614374565b906134e2565b101561192e5760405162461bcd60e51b815260040161043990614844565b6119398b8585613bb5565b83600460008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160701b0302191690836001600160701b03160217905550602082015181600001600e6101000a8154816001600160701b0302191690836001600160701b03160217905550604082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160006101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160010160086101000a8154816001600160701b0302191690836001600160701b0316021790555060a08201518160010160166101000a81548160ff02191690831515021790555090505082600460007f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160701b0302191690836001600160701b03160217905550602082015181600001600e6101000a8154816001600160701b0302191690836001600160701b03160217905550604082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160006101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160010160086101000a8154816001600160701b0302191690836001600160701b0316021790555060a08201518160010160166101000a81548160ff021916908315150217905550905050876001600160a01b03167f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b03168c6001600160a01b03167f74ef34e2ea7c5d9f7b7ed44e97ad44b4303416c3a660c3fb5b3bdb95a1d6abd38d8a8a8d604051611c149493929190614d1b565b60405180910390a4505060016002555091979650505050505050565b6000611c3a610ebb565b15611c575760405162461bcd60e51b8152600401610439906147f6565b6001600160a01b038316611c7d5760405162461bcd60e51b81526004016104399061487b565b7f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b0316836001600160a01b03161415611ccf5760405162461bcd60e51b815260040161043990614c24565b60075460405163022e0a1160e61b81526001600160a01b0390911690638b82844090611d019086908690600401614449565b60006040518083038186803b158015611d1957600080fd5b505afa158015611d2d573d6000803e3d6000fd5b50505050611d3961408a565b506001600160a01b038316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a08201819052611de25760405162461bcd60e51b815260040161043990614aee565b611dea61408a565b507f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b0316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a0820152611ea0858383613387565b611eac8585848461387b565b600754604051632ab6f78f60e01b81529194506001600160a01b031690632ab6f78f90611f039088907f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b759089908990600401614420565b60006040518083038186803b158015611f1b57600080fd5b505afa158015611f2f573d6000803e3d6000fd5b5050600854604051633409528b60e21b815260009350611fc192506001600160a01b039091169063d0254a2c90611f6a908a906004016143e8565b60206040518083038186803b158015611f8257600080fd5b505afa158015611f96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fba9190614374565b85906134c5565b9050611fcd84826134e2565b6040516370a0823160e01b81529094506001600160a01b037f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b7516906370a082319061201c9030906004016143e8565b60206040518083038186803b15801561203457600080fd5b505afa158015612048573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061206c9190614374565b84111561131e5760405162461bcd60e51b8152600401610439906145c0565b6000546001600160a01b03163314806120b357503360009081526005602052604090205460ff165b6120cf5760405162461bcd60e51b8152600401610439906149d2565b610722613d15565b6001546001600160a01b031681565b6002805414156121085760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b031633148061213457503360009081526005602052604090205460ff165b6121505760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b0381166121765760405162461bcd60e51b815260040161043990614c5b565b600680546001600160a01b0319166001600160a01b0383169081179091556040517f59ddfdd1bf7e3ea08a07e8aaa1fe2ce9c840fab69fe5ede6ea727a45eb42fc6690600090a2506001600255565b6002805414156121e75760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b031633148061221357503360009081526005602052604090205460ff165b61222f5760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b0381166122555760405162461bcd60e51b81526004016104399061465b565b6001600160a01b038116600090815260046020526040902060010154600160b01b900460ff166122975760405162461bcd60e51b815260040161043990614aee565b6001600160a01b03811660008181526004602052604080822082815560010180546001600160b81b0319169055517f5a1f36141a0cb942bd02bfae3796688b4c89d39ca58a36b286c71492a9b18012916122f291819061446d565b60405180910390a2506001600255565b6006546001600160a01b031681565b6002805414156123335760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b031633148061235f57503360009081526005602052604090205460ff165b61237b5760405162461bcd60e51b8152600401610439906149d2565b612387600983836140bf565b5050600160025550565b6008546001600160a01b031681565b6002805414156123c25760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b031633146123f05760405162461bcd60e51b8152600401610439906148b2565b6001600160a01b0383166124165760405162461bcd60e51b815260040161043990614a01565b6001600160a01b03821661243c5760405162461bcd60e51b8152600401610439906148e9565b61244783838361326e565b816001600160a01b0316836001600160a01b03167f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb8360405161248a9190614cdc565b60405180910390a35050600160025550565b6002805414156124be5760405162461bcd60e51b815260040161043990614ba9565b600280556000546001600160a01b03163314806124ea57503360009081526005602052604090205460ff165b6125065760405162461bcd60e51b8152600401610439906149d2565b6001600160a01b03831661252c5760405162461bcd60e51b81526004016104399061465b565b7f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b0316836001600160a01b0316141561257e5760405162461bcd60e51b815260040161043990614c24565b6001600160701b038211156125a55760405162461bcd60e51b8152600401610439906144ef565b670de0b6b3a76400008111156125cd5760405162461bcd60e51b815260040161043990614abf565b6125d561408a565b506001600160a01b038316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff1615801560a083015261267d5760405162461bcd60e51b8152600401610439906147bf565b6001600160701b038316602082018190526001600160401b038316606083015260808201516126ac919061335c565b6001600160701b0390811660808301908152600160a084018181526001600160a01b03881660008181526004602090815260409182902088518154928a0151848b015163ffffffff16600160e01b026001600160e01b03918b16600160701b02600160701b600160e01b0319938c166001600160701b031990961695909517929092169390931792909216919091178155606088015194018054955193511515600160b01b0260ff60b01b1994909716600160401b02600160401b600160b01b03196001600160401b0390961667ffffffffffffffff1990971696909617949094169490941791909116939093179055517f5a1f36141a0cb942bd02bfae3796688b4c89d39ca58a36b286c71492a9b1801290610ea8908690869061446d565b6000546001600160a01b031633146127f65760405162461bcd60e51b8152600401610439906148b2565b600080546040516001600160a01b03808516939216917fdcf55418cee3220104fef63f979ff3c4097ad240c0c43dcb33ce837748983e6291a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b60006002805414156128755760405162461bcd60e51b815260040161043990614ba9565b60028055612881610ebb565b1561289e5760405162461bcd60e51b8152600401610439906147f6565b6001600160a01b0386166128c45760405162461bcd60e51b81526004016104399061487b565b6001600160a01b0383166128ea5760405162461bcd60e51b8152600401610439906148e9565b7f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b0316866001600160a01b0316141561293c5760405162461bcd60e51b815260040161043990614c24565b60075460405163022e0a1160e61b81526001600160a01b0390911690638b8284409061298e907f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75908990600401614449565b60006040518083038186803b1580156129a657600080fd5b505afa1580156129ba573d6000803e3d6000fd5b5050505060003390506129cb61408a565b506001600160a01b038716600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a08201819052612a745760405162461bcd60e51b815260040161043990614aee565b612a7c61408a565b507f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b0316600090815260046020908152604091829020825160c08101845281546001600160701b038082168352600160701b8204811694830194909452600160e01b900463ffffffff1693810193909352600101546001600160401b0381166060840152600160401b81049091166080830152600160b01b900460ff16151560a0820152612b32898383613387565b612b5e7f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b7584308b61378a565b600854604051633409528b60e21b8152600091612bec916001600160a01b039091169063d0254a2c90612b95908e906004016143e8565b60206040518083038186803b158015612bad57600080fd5b505afa158015612bc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be59190614374565b8a906134c5565b9050612bf889826134e2565b9850612c068a8a858561350a565b945087851015612c285760405162461bcd60e51b815260040161043990614788565b600854612c60907f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75906001600160a01b031683613ace565b600854604051633ffbd86960e11b81526001600160a01b0390911690637ff7b0d290612c929084908a90600401614ce5565b600060405180830381600087803b158015612cac57600080fd5b505af1158015612cc0573d6000803e3d6000fd5b5050600754604051632ab6f78f60e01b81526001600160a01b039091169250632ab6f78f9150612d1a907f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75908e908e908b90600401614420565b60006040518083038186803b158015612d3257600080fd5b505afa158015612d46573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506001600160a01b038d1691506370a0823190612d79908b906004016143e8565b60206040518083038186803b158015612d9157600080fd5b505afa158015612da5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dc99190614374565b9050612dd68b898861326e565b88612e07828d6001600160a01b03166370a082318c6040518263ffffffff1660e01b81526004016118ba91906143e8565b1015612e255760405162461bcd60e51b815260040161043990614844565b612e308b8585613bb5565b83600460008d6001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160701b0302191690836001600160701b03160217905550602082015181600001600e6101000a8154816001600160701b0302191690836001600160701b03160217905550604082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160006101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160010160086101000a8154816001600160701b0302191690836001600160701b0316021790555060a08201518160010160166101000a81548160ff02191690831515021790555090505082600460007f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160701b0302191690836001600160701b03160217905550602082015181600001600e6101000a8154816001600160701b0302191690836001600160701b03160217905550604082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160010160006101000a8154816001600160401b0302191690836001600160401b0316021790555060808201518160010160086101000a8154816001600160701b0302191690836001600160701b0316021790555060a08201518160010160166101000a81548160ff021916908315150217905550905050876001600160a01b03168b6001600160a01b03167f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b03167f74ef34e2ea7c5d9f7b7ed44e97ad44b4303416c3a660c3fb5b3bdb95a1d6abd361310a868f613d7090919063ffffffff16565b8a8a8d604051611c149493929190614d1b565b600460205260009081526040902080546001909101546001600160701b0380831692600160701b8104821692600160e01b90910463ffffffff16916001600160401b03821691600160401b810490911690600160b01b900460ff1686565b6040516370a0823160e01b81526000906001600160a01b038316906370a08231906131aa9030906004016143e8565b60206040518083038186803b1580156131c257600080fd5b505afa1580156131d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131fa9190614374565b92915050565b613208610ebb565b6132245760405162461bcd60e51b81526004016104399061455b565b6003805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa613257613d95565b60405161326491906143e8565b60405180910390a1565b60006060846001600160a01b031663a9059cbb8585604051602401613294929190614449565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516132cd91906143cc565b6000604051808303816000865af19150503d806000811461330a576040519150601f19603f3d011682016040523d82523d6000602084013e61330f565b606091505b509150915081801561333957508051158061333957508080602001905181019061333991906142ec565b6133555760405162461bcd60e51b815260040161043990614b25565b5050505050565b6000816001600160701b0316836001600160701b0316101561337e5781613380565b825b9392505050565b6001600160a01b0383166133ad5760405162461bcd60e51b815260040161043990614589565b6133b8838383613bb5565b60065460408051635c03bbf560e11b815290516000926001600160a01b03169163b80777ea916004808301926020929190829003018186803b1580156133fd57600080fd5b505afa158015613411573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134359190614374565b9050826040015163ffffffff168163ffffffff161461347b576134608360200151846000015161335c565b6001600160701b0316608084015263ffffffff811660408401525b816040015163ffffffff168163ffffffff16146134bf576134a48260200151836000015161335c565b6001600160701b0316608083015263ffffffff811660408301525b50505050565b60006133806134d48484613d99565b670de0b6b3a7640000613dd3565b6000828211156135045760405162461bcd60e51b8152600401610439906146e3565b50900390565b6006546040516331e658a560e01b815260009182918291829182916001600160a01b0316906331e658a590613543908c906004016143e8565b60806040518083038186803b15801561355b57600080fd5b505afa15801561356f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613593919061438c565b92965090945092509050806135ba5760405162461bcd60e51b815260040161043990614526565b60075460405163927e40cf60e01b81526001600160a01b039091169063927e40cf9061360e9087908d907f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b7590600401614cfc565b60006040518083038186803b15801561362657600080fd5b505afa15801561363a573d6000803e3d6000fd5b5050505061366e611fba61365f671bc16d674ec8000086613e0090919063ffffffff16565b670de0b6b3a764000090613d70565b9350600080613681898988876000613e1d565b909250905080156137205760006136a787868c606001516001600160401b031685613f92565b9050818b11156136e55760006136bd8c846134e2565b90506136dd6136d68988670de0b6b3a764000085613fcc565b8390613d70565b98505061371a565b60006136f1838d6134e2565b905061371661370f89888e606001516001600160401b031685613f92565b83906134e2565b9850505b5061377c565b60006137368786670de0b6b3a764000086613fe6565b905060006137448c83613d70565b9050600061375c8988670de0b6b3a764000085613fcc565b905084811161376c576000613776565b61377681866134e2565b99505050505b505050505050949350505050565b60006060856001600160a01b03166323b872dd8686866040516024016137b2939291906143fc565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516137eb91906143cc565b6000604051808303816000865af19150503d8060008114613828576040519150601f19603f3d011682016040523d82523d6000602084013e61382d565b606091505b509150915081801561385757508051158061385757508080602001905181019061385791906142ec565b6138735760405162461bcd60e51b815260040161043990614692565b505050505050565b6006546040516331e658a560e01b815260009182918291829182916001600160a01b0316906331e658a5906138b4908c906004016143e8565b60806040518083038186803b1580156138cc57600080fd5b505afa1580156138e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613904919061438c565b929650909450925090508061392b5760405162461bcd60e51b815260040161043990614526565b60075460405163927e40cf60e01b81526001600160a01b039091169063927e40cf9061397f9087908d907f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b7590600401614cfc565b60006040518083038186803b15801561399757600080fd5b505afa1580156139ab573d6000803e3d6000fd5b505050506139e66139df6139d0671bc16d674ec8000086613e0090919063ffffffff16565b670de0b6b3a7640000906134e2565b8590614008565b93506000806139f9898988876001613e1d565b90925090508115613a78576000613a1f87868c606001516001600160401b031686613fe6565b9050828b1115613a4e576000613a358c856134e2565b90506136dd6136d68988670de0b6b3a76400008561402c565b6000613a5a848d6134e2565b905061371661370f89888e606001516001600160401b031685613fe6565b6000613a8e8786670de0b6b3a764000085613f92565b90506000613a9c8c83613d70565b90506000613ab48988670de0b6b3a76400008561402c565b9050838111613ac4576000613776565b61377681856134e2565b60006060846001600160a01b031663095ea7b38585604051602401613af4929190614449565b6040516020818303038152906040529060e01b6020820180516001600160e01b038381831617835250505050604051613b2d91906143cc565b6000604051808303816000865af19150503d8060008114613b6a576040519150601f19603f3d011682016040523d82523d6000602084013e613b6f565b606091505b5091509150818015613b99575080511580613b99575080806020019051810190613b9991906142ec565b6133555760405162461bcd60e51b815260040161043990614a74565b6040516370a0823160e01b81526000906001600160a01b038516906370a0823190613be49030906004016143e8565b60206040518083038186803b158015613bfc57600080fd5b505afa158015613c10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c349190614374565b905060007f00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b756001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401613c8491906143e8565b60206040518083038186803b158015613c9c57600080fd5b505afa158015613cb0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cd49190614374565b90506001600160701b03821115613cea57600080fd5b6001600160701b03811115613cfe57600080fd5b6001600160701b0391821690935291909116905250565b613d1d610ebb565b15613d3a5760405162461bcd60e51b8152600401610439906147f6565b6003805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258613257613d95565b6000828201838110156133805760405162461bcd60e51b8152600401610439906145ed565b3390565b600082613da8575060006131fa565b82820282848281613db557fe5b04146133805760405162461bcd60e51b815260040161043990614965565b600080613de08484614042565b905082810284038015613df8575060010190506131fa565b5090506131fa565b6000613380613e1784670de0b6b3a7640000613d99565b83613dd3565b600080600087608001516001600160701b031688600001516001600160701b03161015613e685787516080890151613e61916001600160701b0391821691166134e2565b9250613e88565b60808801518851613e85916001600160701b0391821691166134e2565b90505b600087608001516001600160701b031688600001516001600160701b03161015613ed05787516080890151613ec9916001600160701b0391821691166134e2565b9250613ef0565b60808801518851613eed916001600160701b0391821691166134e2565b90505b80613efb83896134c5565b1115613f1957613f0e61370f828961406c565b915060009050613f34565b613f2d613f2683896134c5565b82906134e2565b9050600091505b6000613f4a8888670de0b6b3a764000085613fcc565b90508515158582101415613f5c578094505b6000613f728989670de0b6b3a76400008761402c565b90508615158582111415613f84578094505b505050509550959350505050565b600080613fac6139d085613fa68887614008565b90614008565b9050613fc281613fbc858961406c565b9061406c565b9695505050505050565b600080613fac61365f85613fe088876134c5565b906134c5565b600080613ffc6139d085613fa689818a89614008565b9050613fc281613fbc85895b6000670de0b6b3a764000061401d8484613d99565b8161402457fe5b049392505050565b600080613ffc61365f85613fe089818a896134c5565b60008082116140635760405162461bcd60e51b815260040161043990614751565b81838161402457fe5b60006133808261408485670de0b6b3a7640000613d99565b90614042565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106141005782800160ff1982351617855561412d565b8280016001018555821561412d579182015b8281111561412d578235825591602001919060010190614112565b5061413992915061413d565b5090565b5b80821115614139576000815560010161413e565b600060208284031215614163578081fd5b813561338081614d6e565b60006020828403121561417f578081fd5b815161338081614d6e565b6000806040838503121561419c578081fd5b82356141a781614d6e565b915060208301356141b781614d6e565b809150509250929050565b6000806000606084860312156141d6578081fd5b83356141e181614d6e565b925060208401356141f181614d6e565b929592945050506040919091013590565b60008060408385031215614214578182fd5b823561421f81614d6e565b915060208301356141b781614d86565b60008060408385031215614241578182fd5b823561424c81614d6e565b946020939093013593505050565b60008060006060848603121561426e578283fd5b833561427981614d6e565b95602085013595506040909401359392505050565b600080600080600060a086880312156142a5578081fd5b85356142b081614d6e565b9450602086013593506040860135925060608601356142ce81614d6e565b915060808601356142de81614d6e565b809150509295509295909350565b6000602082840312156142fd578081fd5b815161338081614d86565b6000806020838503121561431a578182fd5b82356001600160401b0380821115614330578384fd5b818501915085601f830112614343578384fd5b813581811115614351578485fd5b866020828501011115614362578485fd5b60209290920196919550909350505050565b600060208284031215614385578081fd5b5051919050565b600080600080608085870312156143a1578384fd5b84519350602085015192506040850151915060608501516143c181614d86565b939692955090935050565b600082516143de818460208701614d42565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b918252602082015260400190565b600060208252825180602084015261449a816040850160208701614d42565b601f01601f19169190910160400192915050565b60208082526021908201527f576f6f50503a2071756f7465416d6f756e743c6d696e51756f7465416d6f756e6040820152601d60fa1b606082015260800190565b6020808252601d908201527f576f6f50503a205448524553484f4c445f4f55545f4f465f52414e4745000000604082015260600190565b6020808252818101527f576f6f50503a204f5241434c455f50524943455f4e4f545f4645415349424c45604082015260600190565b60208082526014908201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604082015260600190565b6020808252601a908201527f576f6f50503a2042415345544f4b454e5f5a45524f5f41444452000000000000604082015260600190565b602080825260139082015272576f6f50503a20494e535546465f51554f544560681b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601e908201527f576f6f50503a206e65774665654d616e616765725f5a45524f5f414444520000604082015260600190565b6020808252601b908201527f576f6f50503a20424153455f544f4b454e5f5a45524f5f414444520000000000604082015260600190565b60208082526031908201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a207472604082015270185b9cd9995c919c9bdb4819985a5b1959607a1b606082015260800190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252601f908201527f576f6f50503a206e6577576f6f477561726469616e5f5a45524f5f4144445200604082015260600190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252601f908201527f576f6f50503a2062617365416d6f756e743c6d696e42617365416d6f756e7400604082015260600190565b6020808252601b908201527f576f6f50503a20544f4b454e5f414c52454144595f4558495354530000000000604082015260600190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252600a9082015269576f6f50503a20523e3160b01b604082015260600190565b6020808252601b908201527f576f6f50503a20494e535546465f4f55545055545f414d4f554e540000000000604082015260600190565b6020808252601a908201527f576f6f50503a2062617365546f6b656e5f5a45524f5f41444452000000000000604082015260600190565b6020808252601f908201527f496e697469616c697a61626c654f776e61626c653a204e4f545f4f574e455200604082015260600190565b6020808252601390820152722bb7b7a8281d103a37afad22a927afa0a2222960691b604082015260600190565b6020808252602f908201527f496e697469616c697a61626c654f776e61626c653a2053484f554c445f4e4f5460408201526e17d09157d253925512505312569151608a1b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260129082015271576f6f50503a20494e535546465f4241534560701b604082015260600190565b60208082526015908201527415dbdbd4140e881393d517d4d51490551151d254d5605a1b604082015260600190565b6020808252601690820152752bb7b7a8281d103a37b5b2b72fad22a927afa0a2222960511b604082015260600190565b60208082526023908201527f496e697469616c697a61626c654f776e61626c653a20494e56414c49445f434c60408201526241494d60e81b606082015260800190565b6020808252602b908201527f5472616e7366657248656c7065723a3a73616665417070726f76653a2061707060408201526a1c9bdd994819985a5b195960aa1b606082015260800190565b602080825260159082015274576f6f50503a20525f4f55545f4f465f52414e474560581b604082015260600190565b6020808252601b908201527f576f6f50503a20544f4b454e5f444f45535f4e4f545f45584953540000000000604082015260600190565b6020808252602d908201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260408201526c185b9cd9995c8819985a5b1959609a1b606082015260800190565b6020808252601b908201527f576f6f50503a20737472617465676973745f5a45524f5f414444520000000000604082015260600190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b60208082526024908201527f576f6f50503a206665654d616e616765725f71756f7465546f6b656e5f494e566040820152631053125160e21b606082015260800190565b6020808252601c908201527f576f6f50503a2062617365546f6b656e3d3d71756f7465546f6b656e00000000604082015260600190565b6020808252601c908201527f576f6f50503a206e6577576f6f7261636c655f5a45524f5f4144445200000000604082015260600190565b6001600160701b039687168152948616602086015263ffffffff9390931660408501526001600160401b03919091166060840152909216608082015290151560a082015260c00190565b90815260200190565b9182526001600160a01b0316602082015260400190565b9283526001600160a01b03918216602084015216604082015260600190565b93845260208401929092526001600160a01b03908116604084015216606082015260800190565b60005b83811015614d5d578181015183820152602001614d45565b838111156134bf5750506000910152565b6001600160a01b0381168114614d8357600080fd5b50565b8015158114614d8357600080fdfea2646970667358221220f2993ee346cef41e5368bcfebfdea754da2f33828e2079ef1ec0afb35997e99764736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75000000000000000000000000209102c0d2e34282494114ea76d5251c8e7ea7ab000000000000000000000000be1a0fcccfa9c9065152b7770b918f7c59914e8d000000000000000000000000128758d0e909624841ab29d53919646bfbda5db2
-----Decoded View---------------
Arg [0] : newQuoteToken (address): 0x04068DA6C83AFCFA0e13ba15A6696662335D5B75
Arg [1] : newWooracle (address): 0x209102c0D2E34282494114ea76D5251c8e7Ea7ab
Arg [2] : newFeeManager (address): 0xBE1a0FccCFA9c9065152B7770B918f7C59914E8D
Arg [3] : newWooGuardian (address): 0x128758d0e909624841AB29D53919646BFBDa5dB2
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75
Arg [1] : 000000000000000000000000209102c0d2e34282494114ea76d5251c8e7ea7ab
Arg [2] : 000000000000000000000000be1a0fcccfa9c9065152b7770b918f7c59914e8d
Arg [3] : 000000000000000000000000128758d0e909624841ab29d53919646bfbda5db2
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
BSC | 100.00% | $0.008936 | 15 | $0.134 |
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.