Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 1,786 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw ERC20 | 16402363 | 686 days ago | IN | 0 ETH | 0.00125802 | ||||
Withdraw ERC20 | 16402361 | 686 days ago | IN | 0 ETH | 0.00132644 | ||||
Withdraw ERC20 | 16402360 | 686 days ago | IN | 0 ETH | 0.00152121 | ||||
Close Position | 16260754 | 706 days ago | IN | 0 ETH | 0.00036516 | ||||
Withdraw ERC20 | 16032826 | 738 days ago | IN | 0 ETH | 0.00309928 | ||||
Set Close Positi... | 16019257 | 740 days ago | IN | 0 ETH | 0.00038082 | ||||
Set Close Positi... | 16019245 | 740 days ago | IN | 0 ETH | 0.00034842 | ||||
Close Position | 15895559 | 757 days ago | IN | 0 ETH | 0.00647265 | ||||
Close Position | 15884413 | 758 days ago | IN | 0 ETH | 0.01126911 | ||||
Close Position | 15874462 | 760 days ago | IN | 0 ETH | 0.00503947 | ||||
Close Position | 15868696 | 761 days ago | IN | 0 ETH | 0.01142593 | ||||
Withdraw ERC20 | 15868630 | 761 days ago | IN | 0 ETH | 0.00476156 | ||||
Withdraw ERC20 | 15868629 | 761 days ago | IN | 0 ETH | 0.00338215 | ||||
Withdraw ERC20 | 15868627 | 761 days ago | IN | 0 ETH | 0.00210658 | ||||
Withdraw ERC20 | 15868625 | 761 days ago | IN | 0 ETH | 0.00173128 | ||||
Close Position | 15853319 | 763 days ago | IN | 0 ETH | 0.00681314 | ||||
Process Fees | 15852878 | 763 days ago | IN | 0 ETH | 0.00059351 | ||||
Perform Upkeep | 15852566 | 763 days ago | IN | 0 ETH | 0.02294702 | ||||
Process Fees | 15852517 | 763 days ago | IN | 0 ETH | 0.00110736 | ||||
Close Position | 15851086 | 763 days ago | IN | 0 ETH | 0.00524944 | ||||
Perform Upkeep | 15850435 | 763 days ago | IN | 0 ETH | 0.0170167 | ||||
Process Fees | 15848640 | 763 days ago | IN | 0 ETH | 0.00115597 | ||||
Process Fees | 15848616 | 763 days ago | IN | 0 ETH | 0.00116043 | ||||
Add Trigger Orde... | 15848315 | 763 days ago | IN | 0 ETH | 0.0008491 | ||||
Perform Upkeep | 15840113 | 765 days ago | IN | 0 ETH | 0.04134485 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
15639566 | 793 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
PerpetualFutures
Compiler Version
v0.8.16+commit.07a7930e
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.8.16; import '@chainlink/contracts/src/v0.8/KeeperCompatible.sol'; import '@openzeppelin/contracts/access/Ownable.sol'; import '@openzeppelin/contracts/interfaces/IERC20.sol'; import './interfaces/IERC20Decimals.sol'; import './interfaces/IFeeReducer.sol'; import './interfaces/IBokkyPooBahsDateTime.sol'; import './IndexHandler.sol'; import './pfYDF.sol'; contract PerpetualFutures is IndexHandler, KeeperCompatibleInterface, Ownable { uint256 constant PERC_DEN = 100000; pfYDF perpsNft; IFeeReducer feeReducer; IBokkyPooBahsDateTime timeLibrary = IBokkyPooBahsDateTime(0x23d23d8F243e57d0b924bff3A3191078Af325101); bool public enabled = true; mapping(address => bool) public settlers; uint8 maxLiquidationsPerUpkeep = 25; address public mainCollateralToken = 0x30dcBa0405004cF124045793E1933C798Af9E66a; mapping(address => bool) _validColl; address[] _allCollTokens; mapping(address => uint256) _allCollTokensInd; uint16 public maxLeverage = 500; // 50x uint8 public maxTriggerOrders = 2; uint256 public minOpenTimeForProfit = 3 hours; uint256 public minPriceDiffForProfit = (PERC_DEN * 15) / 1000; // 1.5% uint256 public openFeePositionSize = (PERC_DEN * 1) / 1000; // 0.1% uint256 public closeFeePositionSize = (PERC_DEN * 1) / 1000; // 0.1% uint256 public closeFeePerDurationUnit = 1 hours; uint256 public closeFeePerDuration = (PERC_DEN * 5) / 100000; // 0.005% / hour uint256 public totalFees; uint256 public totalAmountProfit; uint256 public totalAmountLoss; // collateral token => amount mapping(address => uint256) public amtOpenLong; mapping(address => uint256) public amtOpenShort; mapping(address => uint256) public maxCollateralOpenDiff; struct PositionIndexFeed { IndexFeed feed; uint16 phaseIdStart; uint80 roundIdStart; uint16 phaseIdSettle; uint80 roundIdSettle; } struct TriggerOrder { uint256 idxPriceCurrent; uint256 idxPriceTarget; } struct PositionLifecycle { uint256 openTime; uint256 openFees; uint256 closeTime; uint256 closeFees; uint256 settleCollPriceUSD; // For positions with alternate collateral, USD per collateral token extended to 18 decimals uint256 settleMainPriceUSD; // For positions with alternate collateral, USD per main token extended to 18 decimals } struct Position { PositionIndexFeed[] feeds; PositionLifecycle lifecycle; address collateralToken; uint256 collateralCloseUnsettled; uint256 collateralAmount; uint256 positionAmount; bool isLong; uint16 leverage; uint256 indexPriceStart; uint256 indexPriceSettle; uint256 amountWon; uint256 amountLost; bool isSettled; } // tokenId => Position mapping(uint256 => Position) public positions; // tokenId => address mapping(uint256 => address) public positionOpeners; // tokenId => address mapping(uint256 => address) public positionClosers; // tokenId => orders mapping(uint256 => TriggerOrder[]) public positionTriggerOrders; // tokenId[] uint256[] public allOpenPositions; // tokenId => allOpenPositions index mapping(uint256 => uint256) internal _openPositionsIdx; // tokenId[] uint256[] public allUnsettledPositions; // tokenId => allUnsettledPositions index mapping(uint256 => uint256) internal _unsettledPositionsIdx; event CloseUnsettledPosition(uint256 indexed tokenId); event OpenPosition( uint256 indexed tokenId, address indexed user, uint256 indexPriceStart, uint256 positionCollateral, bool isLong, uint256 leverage ); event ClosePosition( uint256 indexed tokenId, address indexed user, uint256 indexPriceStart, uint256 indexPriceSettle, uint256 amountWon, uint256 amountLost ); event LiquidatePosition(uint256 tokenId); event ClosePositionFromTriggerOrder(uint256 tokenId); event SettlePosition( uint256 tokenId, uint256 mainTokenSettleAmt, uint256 collSettlePrice, uint256 mainSettlePrice ); modifier onlyPositionOwner(uint256 _tokenId) { require(msg.sender == perpsNft.ownerOf(_tokenId), 'must own position'); _; } modifier onlySettler() { require(settlers[msg.sender], 'only settlers'); _; } constructor(string memory _tokenURI) { perpsNft = new pfYDF(_tokenURI); perpsNft.transferOwnership(msg.sender); } function getPerpsNFT() external view returns (address) { return address(perpsNft); } function getAllIndexes() external view returns (Index[] memory) { return indexes; } function getAllValidCollateralTokens() external view returns (address[] memory) { return _allCollTokens; } function getAllUnsettledPositions() external view returns (uint256[] memory) { return allUnsettledPositions; } function getAllPositionTriggerOrders(uint256 _tokenId) external view returns (TriggerOrder[] memory) { return positionTriggerOrders[_tokenId]; } function openPosition( address _collToken, uint256 _indexInd, uint256 _collateral, uint16 _leverage, // 10 == 1x, 1000 == 100x bool _isLong, uint256 _triggerOrderTargetPrice ) external { require(enabled, 'DISABLED'); require(_indexInd < indexes.length, 'INVIDX'); require(_leverage >= 10 && _leverage <= maxLeverage, 'LEV1'); require(canOpenPositionAgainstIndex(_indexInd, 0), 'INDOOB1'); require( _collToken == address(0) || _collToken == mainCollateralToken || _validColl[_collToken], 'POSTOKEN1' ); IERC20 _collCont = _collToken == address(0) ? IERC20(mainCollateralToken) : IERC20(_collToken); require(_collCont.balanceOf(msg.sender) >= _collateral, 'BAL1'); uint256 _newTokenId = perpsNft.mint(msg.sender); _collCont.transferFrom(msg.sender, address(this), _collateral); uint256 _openFee = _getPositionOpenFee(_collateral, _leverage); uint256 _finalPositionCollateral = _collateral - _openFee; totalFees += _openFee; Index memory _index = indexes[_indexInd]; Position storage _newPosition = positions[_newTokenId]; for (uint256 _i = 0; _i < _index.priceFeeds.length; _i++) { IndexFeed memory _feed = _index.priceFeeds[_i]; (uint16 _phase, uint80 _round, ) = getLatestProxyInfo(_feed.proxy); _newPosition.feeds.push( PositionIndexFeed({ feed: _index.priceFeeds[_i], phaseIdStart: _phase, roundIdStart: _round, phaseIdSettle: 0, roundIdSettle: 0 }) ); } uint256 _openPrice = getIndexPriceFromIndex(_indexInd); positionOpeners[_newTokenId] = msg.sender; _newPosition.lifecycle.openTime = block.timestamp; _newPosition.lifecycle.openFees = _openFee; _newPosition.collateralAmount = _finalPositionCollateral; _newPosition.positionAmount = (_finalPositionCollateral * _leverage) / 10; _newPosition.isLong = _isLong; _newPosition.leverage = _leverage; _newPosition.indexPriceStart = _openPrice; _newPosition.collateralToken = address(_collCont); _addOpenPosition(_newTokenId); _validateAndUpdateOpenAmounts(_newTokenId); if (_triggerOrderTargetPrice > 0) { _addTriggerOrder(_newTokenId, _triggerOrderTargetPrice); } emit OpenPosition( _newTokenId, msg.sender, _openPrice, _finalPositionCollateral, _isLong, _leverage ); } function canOpenPositionAgainstIndex(uint256 _ind, uint256 _timestamp) public view returns (bool) { _timestamp = _timestamp == 0 ? block.timestamp : _timestamp; Index memory _index = indexes[_ind]; if (_index.dowOpenMin >= 1 && _index.dowOpenMax >= 1) { uint256 _dow = timeLibrary.getDayOfWeek(_timestamp); if (_dow < _index.dowOpenMin || _dow > _index.dowOpenMax) { return false; } } if (_index.hourOpenMin >= 1 || _index.hourOpenMax >= 1) { uint256 _hour = timeLibrary.getHour(_timestamp); if (_hour < _index.hourOpenMin || _hour > _index.hourOpenMax) { return false; } } return true; } function closePosition(uint256 _tokenId) external { _closePosition(_tokenId, false); } function _closePosition(uint256 _tokenId, bool _overrideOwner) internal { Position storage _position = positions[_tokenId]; address _user = perpsNft.ownerOf(_tokenId); require(_overrideOwner || msg.sender == _user, 'OWNLQ'); require(perpsNft.doesTokenExist(_tokenId), 'CLOSE1'); _getAndClosePositionPLInfo(_tokenId, _user); _removeOpenPosition(_tokenId); _closeIndividualFeeds(_tokenId); _updateCloseAmounts(_tokenId); perpsNft.burn(_tokenId); positionClosers[_tokenId] = _user; emit ClosePosition( _tokenId, _user, _position.indexPriceStart, _position.indexPriceSettle, _position.amountWon, _position.amountLost ); } function settleUnsettledPosition( uint256 _tokenId, uint256 _collPriceUSD, uint256 _mainPriceUSD ) external onlySettler { Position storage _position = positions[_tokenId]; require(!_position.isSettled, 'SET1'); require(_position.collateralCloseUnsettled > 0, 'SET2'); _position.isSettled = true; _position.lifecycle.settleCollPriceUSD = _collPriceUSD; _position.lifecycle.settleMainPriceUSD = _mainPriceUSD; uint256 _mainSettleAmt = (_position.collateralCloseUnsettled * 10**IERC20Decimals(mainCollateralToken).decimals() * _collPriceUSD) / _mainPriceUSD / 10**IERC20Decimals(_position.collateralToken).decimals(); IERC20(mainCollateralToken).transfer( positionClosers[_tokenId], _mainSettleAmt ); // remove from unsettled positions array uint256 _unsetPositionsIdx = _unsettledPositionsIdx[_tokenId]; uint256 _tokenIdMoving = allUnsettledPositions[ allUnsettledPositions.length - 1 ]; delete _unsettledPositionsIdx[_tokenId]; _unsettledPositionsIdx[_tokenIdMoving] = _unsetPositionsIdx; allUnsettledPositions[_unsetPositionsIdx] = _tokenIdMoving; allUnsettledPositions.pop(); emit SettlePosition(_tokenId, _mainSettleAmt, _collPriceUSD, _mainPriceUSD); } function getIndexAndPLInfo(uint256 _tokenId) public view returns ( uint256, uint256, uint256, bool, bool ) { Position memory _position = positions[_tokenId]; bool _canCloseInProfit = true; uint256 _currentIndexPrice = getPositionIndexPrice(_tokenId); bool _settlePriceIsHigher = _currentIndexPrice > _position.indexPriceStart; bool _settlePriceIsLower = _currentIndexPrice < _position.indexPriceStart; uint256 _indexAbsDiffFromOpen = _settlePriceIsHigher ? _currentIndexPrice - _position.indexPriceStart : _position.indexPriceStart - _currentIndexPrice; uint256 _absolutePL = (_position.positionAmount * _indexAbsDiffFromOpen) / _position.indexPriceStart; bool _isProfit = _position.isLong ? _settlePriceIsHigher : _settlePriceIsLower; uint256 _amountReturnToUser = _position.collateralAmount; if (_isProfit) { bool _isOverMinChange = _indexAbsDiffFromOpen >= (_position.indexPriceStart * minPriceDiffForProfit) / PERC_DEN; bool _isPastMinTime = block.timestamp >= _position.lifecycle.openTime + minOpenTimeForProfit; if (_isOverMinChange || _isPastMinTime) { _amountReturnToUser += _absolutePL; } else { _canCloseInProfit = false; } } else { if (_absolutePL > _amountReturnToUser) { _amountReturnToUser = 0; } else { _amountReturnToUser -= _absolutePL; } } return ( _currentIndexPrice, _amountReturnToUser, _absolutePL, _isProfit, _canCloseInProfit ); } function getLiquidationPriceChange(uint256 _tokenId) public view returns (uint256) { // 90% of exact liquidation which would mean 100% deliquency // NOTE: _position.leverage == 10 means 1x // Ex. price start == 100, leverage == 15 (1.5x) // (priceStart / (15 / 10)) * (9 / 10) // (priceStart * 10 / 15) * (9 / 10) // (priceStart / 15) * 9 // (priceStart * 9) / 15 return (positions[_tokenId].indexPriceStart * 9) / positions[_tokenId].leverage; } function getPositionIndexPrice(uint256 _tokenId) public view returns (uint256) { Position memory _position = positions[_tokenId]; address[] memory _proxies = new address[](_position.feeds.length); uint256[] memory _multipliers = new uint256[](_position.feeds.length); for (uint256 _i = 0; _i < _position.feeds.length; _i++) { _proxies[_i] = _position.feeds[_i].feed.proxy; _multipliers[_i] = _position.feeds[_i].feed.priceWeightMult; } return getIndexPriceFromFeeds(_proxies, _multipliers); } function getPositionCloseFees(uint256 _tokenId) public view returns (uint256, uint256) { address _owner = perpsNft.ownerOf(_tokenId); (uint256 _percentOff, uint256 _percOffDenomenator) = _getFeeDiscount( _owner ); uint256 _closingFeePosition = (positions[_tokenId].positionAmount * closeFeePositionSize) / PERC_DEN; uint256 _closingFeeDurationPerUnit = (positions[_tokenId].positionAmount * closeFeePerDuration) / PERC_DEN; uint256 _closingFeeDurationTotal = (_closingFeeDurationPerUnit * (block.timestamp - positions[_tokenId].lifecycle.openTime)) / closeFeePerDurationUnit; // user has discount from fees if (_percentOff > 0) { _closingFeePosition -= (_closingFeePosition * _percentOff) / _percOffDenomenator; _closingFeeDurationTotal -= (_closingFeeDurationTotal * _percentOff) / _percOffDenomenator; } return (_closingFeePosition, _closingFeeDurationTotal); } function getPositionIndexProxies(uint256 _tokenId) external view returns (address[] memory) { PositionIndexFeed[] memory _posFeeds = positions[_tokenId].feeds; address[] memory _proxies = new address[](positions[_tokenId].feeds.length); for (uint256 _i = 0; _i < _posFeeds.length; _i++) { _proxies[_i] = _posFeeds[_i].feed.proxy; } return _proxies; } function addTriggerOrder(uint256 _tokenId, uint256 _idxPriceTarget) external onlyPositionOwner(_tokenId) { _addTriggerOrder(_tokenId, _idxPriceTarget); } function updateTriggerOrder( uint256 _tokenId, uint256 _idx, uint256 _idxPriceTarget ) external onlyPositionOwner(_tokenId) { _updateTriggerOrder(_tokenId, _idx, _idxPriceTarget); } function removeTriggerOrder(uint256 _tokenId, uint256 _idx) external onlyPositionOwner(_tokenId) { _removeTriggerOrder(_tokenId, _idx); } function _addTriggerOrder(uint256 _tokenId, uint256 _idxPriceTarget) internal { require(_idxPriceTarget > 0, 'TO0'); require(positionTriggerOrders[_tokenId].length < maxTriggerOrders, 'TO1'); uint256 _idxPriceCurr = getPositionIndexPrice(_tokenId); require(_idxPriceCurr != _idxPriceTarget, 'TO2'); positionTriggerOrders[_tokenId].push( TriggerOrder({ idxPriceCurrent: _idxPriceCurr, idxPriceTarget: _idxPriceTarget }) ); } function _updateTriggerOrder( uint256 _tokenId, uint256 _idx, uint256 _idxTargetPrice ) internal { require(_idxTargetPrice > 0, 'TO0'); TriggerOrder storage _order = positionTriggerOrders[_tokenId][_idx]; bool _isTargetLess = _order.idxPriceTarget < _order.idxPriceCurrent; // if original target is less than original current, new target must // remain less than, or vice versa for higher than prices require( _isTargetLess ? _idxTargetPrice < _order.idxPriceCurrent : _idxTargetPrice > _order.idxPriceCurrent, 'TO3' ); _order.idxPriceTarget = _idxTargetPrice; } function _removeTriggerOrder(uint256 _tokenId, uint256 _idx) internal { positionTriggerOrders[_tokenId][_idx] = positionTriggerOrders[_tokenId][ positionTriggerOrders[_tokenId].length - 1 ]; positionTriggerOrders[_tokenId].pop(); } function setValidCollateralToken(address _token, bool _isValid) external onlyOwner { require(_validColl[_token] != _isValid, 'change state'); _validColl[_token] = _isValid; if (_isValid) { _allCollTokensInd[_token] = _allCollTokens.length; _allCollTokens.push(_token); } else { uint256 _ind = _allCollTokensInd[_token]; delete _allCollTokensInd[_token]; _allCollTokens[_ind] = _allCollTokens[_allCollTokens.length - 1]; _allCollTokens.pop(); } } function setMainCollateralToken(address _token) external onlyOwner { require(allOpenPositions.length == 0, 'MAINCOLL'); mainCollateralToken = _token; } // 10 == 1x, 1000 == 100x, etc. function setMaxLeverage(uint16 _max) external onlyOwner { require(_max <= 2500, 'max 250x'); maxLeverage = _max; } function setMaxTriggerOrders(uint8 _max) external onlyOwner { maxTriggerOrders = _max; } function setMinOpenTimeForProfit(uint256 _seconds) external onlyOwner { require(_seconds <= 1 days, 'max 1 days'); minOpenTimeForProfit = _seconds; } function setMinPriceDiffForProfit(uint256 _percentage) external onlyOwner { require(_percentage < (PERC_DEN * 3) / 100, 'max 3%'); minPriceDiffForProfit = _percentage; } function setOpenPositionFeePositionSize(uint256 _percentage) external onlyOwner { require(_percentage < (PERC_DEN * 10) / 100, 'max 10%'); openFeePositionSize = _percentage; } function setClosePositionFeePositionSize(uint256 _percentage) external onlyOwner { require(_percentage < (PERC_DEN * 10) / 100, 'max 10%'); closeFeePositionSize = _percentage; } function setClosePositionFeePerDurationUnit(uint256 _seconds) external onlyOwner { require(_seconds >= 10 minutes, 'min 10m'); closeFeePerDurationUnit = _seconds; } function setClosePositionFeePerDuration(uint256 _percentage) external onlyOwner { require(_percentage < (PERC_DEN * 1) / 100, 'max 1%'); closeFeePerDuration = _percentage; } function setSettler(address _wallet, bool _isSettler) external onlyOwner { require(settlers[_wallet] != _isSettler, 'SET3'); settlers[_wallet] = _isSettler; } function setMaxCollateralOpenDiff(address _collateral, uint256 _amount) external onlyOwner { maxCollateralOpenDiff[_collateral] = _amount; } function setMaxLiquidationsPerUpkeep(uint8 _max) external onlyOwner { require(_max > 0, 'min 1'); maxLiquidationsPerUpkeep = _max; } function addIndex( string memory _name, address[] memory _proxies, uint16[] memory _weights ) external onlyOwner { require( _proxies.length > 0 && _proxies.length == _weights.length, 'same len' ); Index storage _newIndex = indexes.push(); _newIndex.name = _name; for (uint256 _i = 0; _i < _proxies.length; _i++) { address _proxy = _proxies[_i]; (, , uint256 _priceUSD) = getLatestProxyInfo(_proxy); require(_priceUSD > 0, 'invalid proxy'); _newIndex.weightsTotal += _proxies.length == 1 ? 0 : _weights[_i]; _newIndex.priceFeeds.push( IndexFeed({ proxy: _proxy, weight: _weights[_i], priceWeightMult: _proxies.length == 1 ? 0 : (_weights[_i] * FACTOR**2) / _priceUSD }) ); } } function removeIndex(uint256 _index) external onlyOwner { indexes[_index] = indexes[indexes.length - 1]; indexes.pop(); } function refreshIndexFeedWeights(uint256 _indexIdx) external onlyOwner { Index storage _index = indexes[_indexIdx]; require(_index.priceFeeds.length > 1, 'ISIDX'); for (uint256 _i = 0; _i < _index.priceFeeds.length; _i++) { (, , uint256 _priceUSD) = getLatestProxyInfo(_index.priceFeeds[_i].proxy); _index.priceFeeds[_i].priceWeightMult = (_index.priceFeeds[_i].weight * FACTOR**2) / _priceUSD; } } function updateIndexOpenTimeBounds( uint256 _indexInd, uint256 _dowOpenMin, uint256 _dowOpenMax, uint256 _hourOpenMin, uint256 _hourOpenMax ) external onlyOwner { Index storage _index = indexes[_indexInd]; _index.dowOpenMin = _dowOpenMin; _index.dowOpenMax = _dowOpenMax; _index.hourOpenMin = _hourOpenMin; _index.hourOpenMax = _hourOpenMax; } function setEnabled(bool _enabled) external onlyOwner { enabled = _enabled; } function setFeeReducer(address _reducer) external onlyOwner { feeReducer = IFeeReducer(_reducer); } function processFees(uint256 _amount) external onlyOwner { IERC20(mainCollateralToken).transfer(mainCollateralToken, _amount); } function withdrawERC20(address _token, uint256 _amount) external onlyOwner { IERC20 _contract = IERC20(_token); _amount = _amount == 0 ? _contract.balanceOf(address(this)) : _amount; require(_amount > 0); _contract.transfer(owner(), _amount); } // https://docs.chain.link/docs/chainlink-keepers/compatible-contracts/ function checkUpkeep( bytes calldata /* checkData */ ) external view override returns ( bool upkeepNeeded, bytes memory /* performData */ ) { for (uint256 _i = 0; _i < allOpenPositions.length; _i++) { uint256 _tokenId = allOpenPositions[_i]; if ( shouldPositionLiquidate(_tokenId) || shouldPositionCloseFromTrigger(_tokenId) ) { upkeepNeeded = true; break; } } } // https://docs.chain.link/docs/chainlink-keepers/compatible-contracts/ function performUpkeep( bytes calldata /* performData */ ) external override { uint8 _liquidations; for (uint256 _i = 0; _i < allOpenPositions.length; _i++) { uint256 _tokenId = allOpenPositions[_i]; bool _shouldLiquidate = shouldPositionLiquidate(_tokenId); bool _triggerClose = shouldPositionCloseFromTrigger(_tokenId); if (_shouldLiquidate || _triggerClose) { _closePosition(_tokenId, true); _liquidations++; if (_shouldLiquidate) { emit LiquidatePosition(_tokenId); } else if (_triggerClose) { emit ClosePositionFromTriggerOrder(_tokenId); } if (_liquidations >= maxLiquidationsPerUpkeep) { break; } } } } function _getFeeDiscount(address _wallet) internal view returns (uint256, uint256) { return address(feeReducer) != address(0) ? feeReducer.percentDiscount(_wallet) : (0, 0); } function _getPositionOpenFee(uint256 _collateral, uint256 _leverage) internal view returns (uint256) { uint256 _positionPreFee = (_collateral * _leverage) / 10; uint256 _openFee = (_positionPreFee * openFeePositionSize) / PERC_DEN; (uint256 _percentOff, uint256 _percOffDenomenator) = _getFeeDiscount( msg.sender ); // user has discount from fees if (_percentOff > 0) { _openFee -= (_openFee * _percentOff) / _percOffDenomenator; } return _openFee; } function _addOpenPosition(uint256 _tokenId) internal { _openPositionsIdx[_tokenId] = allOpenPositions.length; allOpenPositions.push(_tokenId); } function _removeOpenPosition(uint256 _tokenId) internal { uint256 _allPositionsIdx = _openPositionsIdx[_tokenId]; uint256 _tokenIdMoving = allOpenPositions[allOpenPositions.length - 1]; delete _openPositionsIdx[_tokenId]; _openPositionsIdx[_tokenIdMoving] = _allPositionsIdx; allOpenPositions[_allPositionsIdx] = _tokenIdMoving; allOpenPositions.pop(); } function _checkAndSettlePosition( uint256 _tokenId, address _closingUser, uint256 _returnAmount ) internal { Position storage _position = positions[_tokenId]; if (_returnAmount > 0) { if (_position.collateralToken == mainCollateralToken) { _position.isSettled = true; IERC20(_position.collateralToken).transfer(_closingUser, _returnAmount); } else { if (_returnAmount > _position.collateralAmount) { IERC20(_position.collateralToken).transfer( _closingUser, _position.collateralAmount ); _position.collateralCloseUnsettled = _returnAmount - _position.collateralAmount; _unsettledPositionsIdx[_tokenId] = allUnsettledPositions.length; allUnsettledPositions.push(_tokenId); emit CloseUnsettledPosition(_tokenId); } else { _position.isSettled = true; IERC20(_position.collateralToken).transfer( _closingUser, _returnAmount ); } } } else { _position.isSettled = true; } } function _getAndClosePositionPLInfo(uint256 _tokenId, address _closingUser) internal { Position storage _position = positions[_tokenId]; ( uint256 _closingFeePosition, uint256 _closingFeeDurationTotal ) = getPositionCloseFees(_tokenId); uint256 _totalCloseFees = _closingFeePosition + _closingFeeDurationTotal; totalFees += _totalCloseFees; ( uint256 _currentIndexPrice, uint256 _amountReturnToUser, uint256 _absolutePL, bool _isProfit, bool _canCloseInProfit ) = getIndexAndPLInfo(_tokenId); if (_isProfit) { if (_canCloseInProfit) { totalAmountProfit += _absolutePL; } } else { totalAmountLoss += _absolutePL; } // adjust amount returned based on closing fees incurred then transfer to position holder _amountReturnToUser = _totalCloseFees > _amountReturnToUser ? 0 : _amountReturnToUser - _totalCloseFees; _checkAndSettlePosition(_tokenId, _closingUser, _amountReturnToUser); _position.lifecycle.closeTime = block.timestamp; _position.lifecycle.closeFees = _totalCloseFees; _position.indexPriceSettle = _currentIndexPrice; _position.amountWon = _isProfit && _canCloseInProfit ? _absolutePL : 0; _position.amountLost = _isProfit ? 0 : _absolutePL > _position.collateralAmount ? _position.collateralAmount : _absolutePL; } function _closeIndividualFeeds(uint256 _tokenId) internal { Position storage _position = positions[_tokenId]; // update settle phase and round data for all proxies that make up the index for (uint256 _i = 0; _i < _position.feeds.length; _i++) { PositionIndexFeed storage _feed = _position.feeds[_i]; (uint16 _phase, uint80 _round, ) = getLatestProxyInfo(_feed.feed.proxy); _feed.phaseIdSettle = _phase; _feed.roundIdSettle = _round; } } function _validateAndUpdateOpenAmounts(uint256 _tokenId) internal { Position memory _position = positions[_tokenId]; if (_position.isLong) { amtOpenLong[_position.collateralToken] += _position.positionAmount; } else { amtOpenShort[_position.collateralToken] += _position.positionAmount; } if (maxCollateralOpenDiff[_position.collateralToken] > 0) { uint256 _openDiff = amtOpenLong[_position.collateralToken] > amtOpenShort[_position.collateralToken] ? amtOpenLong[_position.collateralToken] - amtOpenShort[_position.collateralToken] : amtOpenShort[_position.collateralToken] - amtOpenLong[_position.collateralToken]; require( _openDiff <= maxCollateralOpenDiff[_position.collateralToken], 'max collateral reached' ); } } function _updateCloseAmounts(uint256 _tokenId) internal { if (positions[_tokenId].isLong) { amtOpenLong[positions[_tokenId].collateralToken] -= positions[_tokenId] .positionAmount; } else { amtOpenShort[positions[_tokenId].collateralToken] -= positions[_tokenId] .positionAmount; } } function shouldPositionLiquidate(uint256 _tokenId) public view returns (bool) { Position memory _position = positions[_tokenId]; uint256 _priceChangeForLiquidation = getLiquidationPriceChange(_tokenId); (uint256 _closingFeeMain, uint256 _closingFeeTime) = getPositionCloseFees( _tokenId ); ( uint256 _currentIndexPrice, uint256 _amountReturnToUser, , bool _isProfit, ) = getIndexAndPLInfo(_tokenId); uint256 _indexPriceDelinquencyPrice = _position.isLong ? _position.indexPriceStart - _priceChangeForLiquidation : _position.indexPriceStart + _priceChangeForLiquidation; bool _priceInLiquidation = _position.isLong ? _currentIndexPrice <= _indexPriceDelinquencyPrice : _currentIndexPrice >= _indexPriceDelinquencyPrice; bool _feesExceedReturn = !_isProfit && _closingFeeMain + _closingFeeTime >= _amountReturnToUser; return _priceInLiquidation || _feesExceedReturn; } function shouldPositionCloseFromTrigger(uint256 _tokenId) public view returns (bool) { TriggerOrder[] memory _orders = positionTriggerOrders[_tokenId]; uint256 _currIdxPrice = getPositionIndexPrice(_tokenId); for (uint256 _i = 0; _i < _orders.length; _i++) { uint256 _target = _orders[_i].idxPriceTarget; bool _lessThanEQ = _target < _orders[_i].idxPriceCurrent; if (_lessThanEQ) { if (_currIdxPrice <= _target) { return true; } } else { if (_currIdxPrice >= _target) { return true; } } } return false; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./KeeperBase.sol"; import "./interfaces/KeeperCompatibleInterface.sol"; abstract contract KeeperCompatible is KeeperBase, KeeperCompatibleInterface {}
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import '@openzeppelin/contracts/interfaces/IERC20.sol'; interface IERC20Decimals is IERC20 { function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; interface IFeeReducer { function percentDiscount(address _user) external view returns (uint256, uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; interface IBokkyPooBahsDateTime { function getDayOfWeek(uint256 timestamp) external pure returns (uint256 dayOfWeek); function getHour(uint256 timestamp) external pure returns (uint256 hour); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import './interfaces/PriceFeedProxy.sol'; contract IndexHandler { uint256 constant FACTOR = 10**18; struct IndexFeed { address proxy; uint16 weight; uint256 priceWeightMult; } struct Index { string name; uint256 weightsTotal; uint256 dowOpenMin; uint256 dowOpenMax; uint256 hourOpenMin; uint256 hourOpenMax; IndexFeed[] priceFeeds; } Index[] public indexes; function getIndexPriceFromIndex(uint256 _index) public view returns (uint256) { Index memory index = indexes[_index]; uint256 priceUSD; for (uint256 i = 0; i < index.priceFeeds.length; i++) { IndexFeed memory _proxy = index.priceFeeds[i]; (, , uint256 _feedPriceUSD) = getLatestProxyInfo(_proxy.proxy); priceUSD += _proxy.priceWeightMult == 0 ? _feedPriceUSD : (_feedPriceUSD * _proxy.priceWeightMult) / FACTOR; } return priceUSD; } function getIndexPriceFromFeeds( address[] memory _proxies, uint256[] memory _multipliers ) public view returns (uint256) { require(_proxies.length == _multipliers.length); uint256 priceUSD; for (uint256 i = 0; i < _proxies.length; i++) { (, , uint256 _feedPriceUSD) = getLatestProxyInfo(_proxies[i]); priceUSD += _proxies.length == 1 ? _feedPriceUSD : (_feedPriceUSD * _multipliers[i]) / FACTOR; } return priceUSD; } function getLatestProxyInfo(address _proxy) public view returns ( uint16, uint80, uint256 ) { PriceFeedProxy _feed = PriceFeedProxy(_proxy); uint16 _phaseId = _feed.phaseId(); uint8 _decimals = _feed.decimals(); (uint80 _proxyRoundId, int256 _price, , , ) = _feed.latestRoundData(); return ( _phaseId, _proxyRoundId, uint256(_price) * (10**18 / 10**_decimals) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import '@chainlink/contracts/src/v0.8/KeeperCompatible.sol'; import '@openzeppelin/contracts/access/Ownable.sol'; import '@openzeppelin/contracts/interfaces/IERC20.sol'; import '@openzeppelin/contracts/token/ERC721/ERC721.sol'; import '@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol'; import '@openzeppelin/contracts/utils/Counters.sol'; import './IndexHandler.sol'; contract pfYDF is ERC721Enumerable, Ownable { using Strings for uint256; using Counters for Counters.Counter; address public perpetualFutures; Counters.Counter internal _ids; string private baseTokenURI; // baseTokenURI can point to IPFS folder like https://ipfs.io/ipfs/{cid}/ while address public royaltyAddress; // Royalties basis points (percentage using 2 decimals - 1000 = 100, 500 = 50, 0 = 0) uint256 private royaltyBasisPoints = 50; // 5% // array of all the NFT token IDs owned by a user mapping(address => uint256[]) public allUserOwned; // the index in the token ID array at allUserOwned to save gas on operations mapping(uint256 => uint256) public ownedIndex; mapping(uint256 => uint256) public tokenMintedAt; mapping(uint256 => uint256) public tokenLastTransferred; event Burn(uint256 indexed tokenId, address indexed owner); event Mint(uint256 indexed tokenId, address indexed owner); event SetPaymentAddress(address indexed user); event SetRoyaltyAddress(address indexed user); event SetRoyaltyBasisPoints(uint256 indexed _royaltyBasisPoints); event SetBaseTokenURI(string indexed newUri); modifier onlyPerps() { require(msg.sender == perpetualFutures, 'only perps'); _; } constructor(string memory _baseTokenURI) ERC721('Yieldification Perpetual Futures', 'pfYDF') { baseTokenURI = _baseTokenURI; perpetualFutures = msg.sender; } function mint(address owner) external onlyPerps returns (uint256) { _ids.increment(); _safeMint(owner, _ids.current()); tokenMintedAt[_ids.current()] = block.timestamp; emit Mint(_ids.current(), owner); return _ids.current(); } function burn(uint256 _tokenId) external onlyPerps { address _user = ownerOf(_tokenId); require(_exists(_tokenId)); _burn(_tokenId); emit Burn(_tokenId, _user); } // Support royalty info - See {EIP-2981}: https://eips.ethereum.org/EIPS/eip-2981 function royaltyInfo(uint256, uint256 _salePrice) external view returns (address receiver, uint256 royaltyAmount) { return (royaltyAddress, (_salePrice * royaltyBasisPoints) / 1000); } function tokenURI(uint256 _tokenId) public view virtual override returns (string memory) { require(_exists(_tokenId)); return string(abi.encodePacked(_baseURI(), _tokenId.toString(), '.json')); } // Contract metadata URI - Support for OpenSea: https://docs.opensea.io/docs/contract-level-metadata function contractURI() public view returns (string memory) { return string(abi.encodePacked(_baseURI(), 'contract.json')); } // Override supportsInterface - See {IERC165-supportsInterface} function supportsInterface(bytes4 _interfaceId) public view virtual override(ERC721Enumerable) returns (bool) { return super.supportsInterface(_interfaceId); } function getLastMintedTokenId() external view returns (uint256) { return _ids.current(); } function doesTokenExist(uint256 _tokenId) external view returns (bool) { return _exists(_tokenId); } function setRoyaltyAddress(address _address) external onlyOwner { royaltyAddress = _address; emit SetRoyaltyAddress(_address); } function setRoyaltyBasisPoints(uint256 _points) external onlyOwner { royaltyBasisPoints = _points; emit SetRoyaltyBasisPoints(_points); } function setBaseURI(string memory _uri) external onlyOwner { baseTokenURI = _uri; emit SetBaseTokenURI(_uri); } function setPerpetualFutures(address _perps) external onlyOwner { perpetualFutures = _perps; } function getAllUserOwned(address _user) external view returns (uint256[] memory) { return allUserOwned[_user]; } function _baseURI() internal view override returns (string memory) { return baseTokenURI; } function _beforeTokenTransfer( address _from, address _to, uint256 _tokenId ) internal virtual override(ERC721Enumerable) { tokenLastTransferred[_tokenId] = block.timestamp; super._beforeTokenTransfer(_from, _to, _tokenId); } function _afterTokenTransfer( address _from, address _to, uint256 _tokenId ) internal virtual override(ERC721) { // if from == address(0), token is being minted if (_from != address(0)) { uint256 _currIndex = ownedIndex[_tokenId]; uint256 _tokenIdMovingIndices = allUserOwned[_from][ allUserOwned[_from].length - 1 ]; allUserOwned[_from][_currIndex] = allUserOwned[_from][ allUserOwned[_from].length - 1 ]; allUserOwned[_from].pop(); ownedIndex[_tokenIdMovingIndices] = _currIndex; } // if to == address(0), token is being burned if (_to != address(0)) { ownedIndex[_tokenId] = allUserOwned[_to].length; allUserOwned[_to].push(_tokenId); } super._afterTokenTransfer(_from, _to, _tokenId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract KeeperBase { error OnlySimulatedBackend(); /** * @notice method that allows it to be simulated via eth_call by checking that * the sender is the zero address. */ function preventExecution() internal view { if (tx.origin != address(0)) { revert OnlySimulatedBackend(); } } /** * @notice modifier that allows it to be simulated via eth_call by checking * that the sender is the zero address. */ modifier cannotExecute() { preventExecution(); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface KeeperCompatibleInterface { /** * @notice method that is simulated by the keepers to see if any work actually * needs to be performed. This method does does not actually need to be * executable, and since it is only ever simulated it can consume lots of gas. * @dev To ensure that it is never called, you may want to add the * cannotExecute modifier from KeeperBase to your implementation of this * method. * @param checkData specified in the upkeep registration so it is always the * same for a registered upkeep. This can easily be broken down into specific * arguments using `abi.decode`, so multiple upkeeps can be registered on the * same contract and easily differentiated by the contract. * @return upkeepNeeded boolean to indicate whether the keeper should call * performUpkeep or not. * @return performData bytes that the keeper should call performUpkeep with, if * upkeep is needed. If you would like to encode data to decode later, try * `abi.encode`. */ function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData); /** * @notice method that is actually executed by the keepers, via the registry. * The data returned by the checkUpkeep simulation will be passed into * this method to actually be executed. * @dev The input to this method should not be trusted, and the caller of the * method should not even be restricted to any single registry. Anyone should * be able call it, and the input should be validated, there is no guarantee * that the data passed in is the performData returned from checkUpkeep. This * could happen due to malicious keepers, racing keepers, or simply a state * change while the performUpkeep transaction is waiting for confirmation. * Always validate the data passed in. * @param performData is the data which was passed back from the checkData * simulation. If it is encoded, it can easily be decoded into other types by * calling `abi.decode`. This data should not be trusted, and should be * validated against the contract's current state. */ function performUpkeep(bytes calldata performData) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; import '@chainlink/contracts/src/v0.8/interfaces/AggregatorV2V3Interface.sol'; interface PriceFeedProxy is AggregatorV2V3Interface { function aggregator() external view returns (address); function phaseId() external view returns (uint16); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./AggregatorInterface.sol"; import "./AggregatorV3Interface.sol"; interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface AggregatorInterface { function latestAnswer() external view returns (int256); function latestTimestamp() external view returns (uint256); function latestRound() external view returns (uint256); function getAnswer(uint256 roundId) external view returns (int256); function getTimestamp(uint256 roundId) external view returns (uint256); event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _owners[tokenId]; require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _owners[tokenId] != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _balances[owner] -= 1; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` 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 tokenId ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "./IERC721Enumerable.sol"; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` cannot be the zero address. * - `to` cannot be the zero address. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library Counters { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
{ "metadata": { "bytecodeHash": "none" }, "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":"string","name":"_tokenURI","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"indexPriceStart","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"indexPriceSettle","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountWon","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountLost","type":"uint256"}],"name":"ClosePosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ClosePositionFromTriggerOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"CloseUnsettledPosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"LiquidatePosition","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"indexPriceStart","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"positionCollateral","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isLong","type":"bool"},{"indexed":false,"internalType":"uint256","name":"leverage","type":"uint256"}],"name":"OpenPosition","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":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mainTokenSettleAmt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collSettlePrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mainSettlePrice","type":"uint256"}],"name":"SettlePosition","type":"event"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"address[]","name":"_proxies","type":"address[]"},{"internalType":"uint16[]","name":"_weights","type":"uint16[]"}],"name":"addIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_idxPriceTarget","type":"uint256"}],"name":"addTriggerOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allOpenPositions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allUnsettledPositions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"amtOpenLong","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"amtOpenShort","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ind","type":"uint256"},{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"canOpenPositionAgainstIndex","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"closeFeePerDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"closeFeePerDurationUnit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"closeFeePositionSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"closePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllIndexes","outputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"weightsTotal","type":"uint256"},{"internalType":"uint256","name":"dowOpenMin","type":"uint256"},{"internalType":"uint256","name":"dowOpenMax","type":"uint256"},{"internalType":"uint256","name":"hourOpenMin","type":"uint256"},{"internalType":"uint256","name":"hourOpenMax","type":"uint256"},{"components":[{"internalType":"address","name":"proxy","type":"address"},{"internalType":"uint16","name":"weight","type":"uint16"},{"internalType":"uint256","name":"priceWeightMult","type":"uint256"}],"internalType":"struct IndexHandler.IndexFeed[]","name":"priceFeeds","type":"tuple[]"}],"internalType":"struct IndexHandler.Index[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getAllPositionTriggerOrders","outputs":[{"components":[{"internalType":"uint256","name":"idxPriceCurrent","type":"uint256"},{"internalType":"uint256","name":"idxPriceTarget","type":"uint256"}],"internalType":"struct PerpetualFutures.TriggerOrder[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllUnsettledPositions","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllValidCollateralTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getIndexAndPLInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_proxies","type":"address[]"},{"internalType":"uint256[]","name":"_multipliers","type":"uint256[]"}],"name":"getIndexPriceFromFeeds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getIndexPriceFromIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_proxy","type":"address"}],"name":"getLatestProxyInfo","outputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint80","name":"","type":"uint80"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getLiquidationPriceChange","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerpsNFT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getPositionCloseFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getPositionIndexPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getPositionIndexProxies","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"indexes","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"weightsTotal","type":"uint256"},{"internalType":"uint256","name":"dowOpenMin","type":"uint256"},{"internalType":"uint256","name":"dowOpenMax","type":"uint256"},{"internalType":"uint256","name":"hourOpenMin","type":"uint256"},{"internalType":"uint256","name":"hourOpenMax","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mainCollateralToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxCollateralOpenDiff","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxLeverage","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTriggerOrders","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minOpenTimeForProfit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minPriceDiffForProfit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openFeePositionSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collToken","type":"address"},{"internalType":"uint256","name":"_indexInd","type":"uint256"},{"internalType":"uint256","name":"_collateral","type":"uint256"},{"internalType":"uint16","name":"_leverage","type":"uint16"},{"internalType":"bool","name":"_isLong","type":"bool"},{"internalType":"uint256","name":"_triggerOrderTargetPrice","type":"uint256"}],"name":"openPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"performUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"positionClosers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"positionOpeners","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"positionTriggerOrders","outputs":[{"internalType":"uint256","name":"idxPriceCurrent","type":"uint256"},{"internalType":"uint256","name":"idxPriceTarget","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"positions","outputs":[{"components":[{"internalType":"uint256","name":"openTime","type":"uint256"},{"internalType":"uint256","name":"openFees","type":"uint256"},{"internalType":"uint256","name":"closeTime","type":"uint256"},{"internalType":"uint256","name":"closeFees","type":"uint256"},{"internalType":"uint256","name":"settleCollPriceUSD","type":"uint256"},{"internalType":"uint256","name":"settleMainPriceUSD","type":"uint256"}],"internalType":"struct PerpetualFutures.PositionLifecycle","name":"lifecycle","type":"tuple"},{"internalType":"address","name":"collateralToken","type":"address"},{"internalType":"uint256","name":"collateralCloseUnsettled","type":"uint256"},{"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"internalType":"uint256","name":"positionAmount","type":"uint256"},{"internalType":"bool","name":"isLong","type":"bool"},{"internalType":"uint16","name":"leverage","type":"uint16"},{"internalType":"uint256","name":"indexPriceStart","type":"uint256"},{"internalType":"uint256","name":"indexPriceSettle","type":"uint256"},{"internalType":"uint256","name":"amountWon","type":"uint256"},{"internalType":"uint256","name":"amountLost","type":"uint256"},{"internalType":"bool","name":"isSettled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"processFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_indexIdx","type":"uint256"}],"name":"refreshIndexFeedWeights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"removeIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_idx","type":"uint256"}],"name":"removeTriggerOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percentage","type":"uint256"}],"name":"setClosePositionFeePerDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_seconds","type":"uint256"}],"name":"setClosePositionFeePerDurationUnit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percentage","type":"uint256"}],"name":"setClosePositionFeePositionSize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_reducer","type":"address"}],"name":"setFeeReducer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"setMainCollateralToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setMaxCollateralOpenDiff","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_max","type":"uint16"}],"name":"setMaxLeverage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_max","type":"uint8"}],"name":"setMaxLiquidationsPerUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_max","type":"uint8"}],"name":"setMaxTriggerOrders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_seconds","type":"uint256"}],"name":"setMinOpenTimeForProfit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percentage","type":"uint256"}],"name":"setMinPriceDiffForProfit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percentage","type":"uint256"}],"name":"setOpenPositionFeePositionSize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"},{"internalType":"bool","name":"_isSettler","type":"bool"}],"name":"setSettler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"bool","name":"_isValid","type":"bool"}],"name":"setValidCollateralToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_collPriceUSD","type":"uint256"},{"internalType":"uint256","name":"_mainPriceUSD","type":"uint256"}],"name":"settleUnsettledPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"settlers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"shouldPositionCloseFromTrigger","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"shouldPositionLiquidate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAmountLoss","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAmountProfit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_indexInd","type":"uint256"},{"internalType":"uint256","name":"_dowOpenMin","type":"uint256"},{"internalType":"uint256","name":"_dowOpenMax","type":"uint256"},{"internalType":"uint256","name":"_hourOpenMin","type":"uint256"},{"internalType":"uint256","name":"_hourOpenMax","type":"uint256"}],"name":"updateIndexOpenTimeBounds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_idx","type":"uint256"},{"internalType":"uint256","name":"_idxPriceTarget","type":"uint256"}],"name":"updateTriggerOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052600480546001600160a81b0319908116740123d23d8f243e57d0b924bff3a3191078af32510117909155600680549091167430dcba0405004cf124045793e1933c798af9e66a19179055600a805462ffffff1916620201f4179055612a30600b556103e862000078620186a0600f6200023b565b62000084919062000269565b600c556103e86200009a620186a060016200023b565b620000a6919062000269565b600d556103e8620000bc620186a060016200023b565b620000c8919062000269565b600e55610e10600f55620186a0620000e28160056200023b565b620000ee919062000269565b601055348015620000fe57600080fd5b5060405162008a3b38038062008a3b8339810160408190526200012191620002c8565b6200012c33620001db565b806040516200013b906200022d565b62000147919062000380565b604051809103906000f08015801562000164573d6000803e3d6000fd5b50600280546001600160a01b0319166001600160a01b0392909216918217905560405163f2fde38b60e01b815233600482015263f2fde38b90602401600060405180830381600087803b158015620001bb57600080fd5b505af1158015620001d0573d6000803e3d6000fd5b5050505050620003b5565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6126c1806200637a83390190565b60008160001904831182151516156200026457634e487b7160e01b600052601160045260246000fd5b500290565b6000826200028757634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620002bf578181015183820152602001620002a5565b50506000910152565b600060208284031215620002db57600080fd5b81516001600160401b0380821115620002f357600080fd5b818401915084601f8301126200030857600080fd5b8151818111156200031d576200031d6200028c565b604051601f8201601f19908116603f011681019083821181831017156200034857620003486200028c565b816040528281528760208487010111156200036257600080fd5b62000375836020830160208801620002a2565b979650505050505050565b6020815260008251806020840152620003a1816040850160208701620002a2565b601f01601f19169190910160400192915050565b615fb580620003c56000396000f3fe608060405234801561001057600080fd5b50600436106104285760003560e01c80638f0525ec1161022b578063d19529ff11610130578063e34274ef116100b8578063f53d9ec111610087578063f53d9ec114610aeb578063f5ae090c14610afe578063f707159714610b07578063fd5891c414610b1a578063fffa41b114610b2d57600080fd5b8063e34274ef14610a9f578063e867d90414610ab2578063ee9b802714610ac5578063f2fde38b14610ad857600080fd5b8063dc731318116100ff578063dc73131814610a48578063df72ad2714610a5b578063e03527d514610a70578063e0a3614314610a83578063e282f76014610a9657600080fd5b8063d19529ff146109f1578063d2c76d74146109fa578063d5e3483614610a0d578063d834123e14610a3557600080fd5b8063adfa3199116101b3578063b91d08ce11610182578063b91d08ce14610996578063ba93fd90146109a9578063c70a900f146109b2578063cb038907146109d5578063d14d40bb146109e857600080fd5b8063adfa319914610946578063ae3302c214610959578063b54710e71461097a578063b81bb7101461098d57600080fd5b806399fbab88116101fa57806399fbab881461081f578063a126d601146108f8578063a1db97821461090b578063a2f0a1f21461091e578063a52e53691461093357600080fd5b80638f0525ec146107a957806391bb214b146107bc57806392f8eb94146107d157806396e61bc7146107f657600080fd5b806356c308ca116103315780636b4b6866116102b95780637c011be8116102885780637c011be8146107445780637f3b7a0214610757578063861d1dfa1461076057806389701db5146107855780638da5cb5b1461079857600080fd5b80636b4b6866146106f55780636e04ff0d14610708578063715018a61461072957806377a354651461073157600080fd5b80635ba87310116103005780635ba873101461067c5780635bc412d91461068f57806362c7536d146106a257806365f290f7146106c257806366c62643146106e257600080fd5b806356c308ca14610608578063589201401461061b578063594a60ae146106565780635ad15eda1461066957600080fd5b8063328d8f72116103b45780633db52911116103835780633db52911146105ae5780634585e33b146105c157806348bb4e33146105d45780634dfdeee5146105e75780634f8f5332146105f057600080fd5b8063328d8f721461053f578063335db3061461055257806339d99cca146105725780633a2baafd1461058557600080fd5b8063174b6399116103fb578063174b639914610496578063182d8747146104b65780631a090154146104d95780631a79344c146104ec578063238dafe01461052b57600080fd5b80630679d3621461042d5780630f1627931461044257806310edc9801461046857806313114a9d1461048d575b600080fd5b61044061043b3660046151d6565b610b40565b005b6104556104503660046151fa565b610ba6565b6040519081526020015b60405180910390f35b6002546001600160a01b03165b6040516001600160a01b03909116815260200161045f565b61045560115481565b6104556104a4366004615228565b60166020526000908152604090205481565b6104c96104c43660046151fa565b610dc9565b604051901515815260200161045f565b6104406104e73660046151fa565b610ef0565b6104ff6104fa3660046151fa565b611043565b60408051958652602086019490945292840191909152151560608301521515608082015260a00161045f565b6004546104c990600160a01b900460ff1681565b61044061054d366004615253565b611364565b6105656105603660046151fa565b61138a565b60405161045f9190615270565b6104406105803660046152ce565b611410565b6104756105933660046151fa565b6018602052600090815260409020546001600160a01b031681565b6104c96105bc3660046152eb565b611469565b6104406105cf36600461530d565b611771565b6104406105e23660046152ce565b61188d565b610455600c5481565b6006546104759061010090046001600160a01b031681565b6104406106163660046151fa565b6118b3565b61062e610629366004615228565b6118fc565b6040805161ffff90941684526001600160501b0390921660208401529082015260600161045f565b61044061066436600461537f565b611a7a565b6104c96106773660046151fa565b611b22565b61045561068a3660046151fa565b611db2565b61044061069d3660046151fa565b611dd3565b6104556106b0366004615228565b60156020526000908152604090205481565b6104556106d0366004615228565b60146020526000908152604090205481565b6104406106f03660046151fa565b611e31565b6104406107033660046152eb565b611e8f565b61071b61071636600461530d565b611f36565b60405161045f9291906153f1565b610440611fab565b61044061073f366004615414565b611fbf565b6104406107523660046152eb565b61204b565b610455600e5481565b600a546107739062010000900460ff1681565b60405160ff909116815260200161045f565b6104406107933660046151fa565b6120f2565b6001546001600160a01b0316610475565b6104556107b73660046151fa565b612178565b6107c46121b1565b60405161045f919061544d565b6107e46107df3660046151fa565b612213565b60405161045f9695949392919061549a565b6104756108043660046151fa565b6019602052600090815260409020546001600160a01b031681565b6108e061082d3660046151fa565b601760209081526000918252604091829020825160c081018452600182015481526002820154928101929092526003810154928201929092526004820154606082015260058201546080820152600682015460a0820152600782015460088301546009840154600a850154600b860154600c870154600d880154600e890154600f8a01546010909a015498996001600160a01b039098169896979596949560ff8086169661010090960461ffff1695168c565b60405161045f9c9b9a999897969594939291906154d6565b6104406109063660046151fa565b6122e7565b610440610919366004615594565b6122f5565b610926612413565b60405161045f91906155c0565b6104406109413660046156c3565b6125be565b6104406109543660046151fa565b612db8565b600a546109679061ffff1681565b60405161ffff909116815260200161045f565b6107c46109883660046151fa565b612e17565b610455600f5481565b6104556109a43660046151fa565b612faf565b610455600d5481565b6104c96109c0366004615228565b60056020526000908152604090205460ff1681565b6104406109e33660046151fa565b612fbf565b61045560105481565b610455600b5481565b610440610a08366004615594565b61300c565b610a20610a1b3660046151fa565b613030565b6040805192835260208301919091520161045f565b610440610a43366004615228565b6131a7565b610a20610a563660046152eb565b6131d1565b610a6361320d565b60405161045f919061572a565b610440610a7e36600461537f565b613264565b610440610a913660046151fa565b613615565b61045560135481565b610455610aad3660046151fa565b613674565b610440610ac0366004615228565b6139a7565b610440610ad3366004615414565b613a12565b610440610ae6366004615228565b613bd5565b610440610af93660046151fa565b613c4b565b61045560125481565b610455610b15366004615841565b613d6c565b610440610b28366004615960565b613e19565b610440610b3b366004615a3c565b614076565b610b486140c1565b6109c48161ffff161115610b8e5760405162461bcd60e51b81526020600482015260086024820152670dac2f040646a60f60c31b60448201526064015b60405180910390fd5b600a805461ffff191661ffff92909216919091179055565b60008060008381548110610bbc57610bbc615a77565b90600052602060002090600702016040518060e0016040529081600082018054610be590615a8d565b80601f0160208091040260200160405190810160405280929190818152602001828054610c1190615a8d565b8015610c5e5780601f10610c3357610100808354040283529160200191610c5e565b820191906000526020600020905b815481529060010190602001808311610c4157829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201805480602002602001604051908101604052809291908181526020016000905b82821015610d19576000848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b900461ffff1683850152600190810154918301919091529083529092019101610cbe565b50505091525090915060009050805b8260c0015151811015610dc15760008360c001518281518110610d4d57610d4d615a77565b602002602001015190506000610d6682600001516118fc565b925050508160400151600014610d9e57670de0b6b3a7640000826040015182610d8f9190615add565b610d999190615afc565b610da0565b805b610daa9085615b1e565b935050508080610db990615b31565b915050610d28565b509392505050565b6000818152601a6020908152604080832080548251818502810185019093528083528493849084015b82821015610e3857838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610df2565b5050505090506000610e4984613674565b905060005b8251811015610ee5576000838281518110610e6b57610e6b615a77565b60200260200101516020015190506000848381518110610e8d57610e8d615a77565b602002602001015160000151821090508015610ebc57818411610eb7575060019695505050505050565b610ed0565b818410610ed0575060019695505050505050565b50508080610edd90615b31565b915050610e4e565b506000949350505050565b610ef86140c1565b6000808281548110610f0c57610f0c615a77565b906000526020600020906007020190506001816006018054905011610f5b5760405162461bcd60e51b8152602060048201526005602482015264092a69288b60db1b6044820152606401610b85565b60005b600682015481101561103e576000610fa3836006018381548110610f8457610f84615a77565b60009182526020909120600290910201546001600160a01b03166118fc565b92505050806002670de0b6b3a7640000610fbd9190615c26565b846006018481548110610fd257610fd2615a77565b6000918252602090912060029091020154610ff89190600160a01b900461ffff16615add565b6110029190615afc565b83600601838154811061101757611017615a77565b6000918252602090912060016002909202010155508061103681615b31565b915050610f5e565b505050565b60008060008060008060176000888152602001908152602001600020604051806101a001604052908160008201805480602002602001604051908101604052809291908181526020016000905b8282101561113757600084815260209081902060408051610100810182526003860290920180546001600160a01b03811660a0850190815261ffff600160a01b909204821660c086015260018084015460e0870152908552600290920154808216858701526001600160501b03620100008204811694860194909452600160601b81049091166060850152600160701b900490911660808301529083529092019101611090565b505050908252506040805160c080820183526001858101548352600286015460208481019190915260038701548486015260048701546060808601919091526005880154608080870191909152600689015460a0808801919091529288019590955260078801546001600160a01b031695870195909552600887015494860194909452600986015492850192909252600a85015492840192909252600b84015460ff80821615159385019390935261ffff610100918290041660e0850152600c85015490840152600d840154610120840152600e840154610140840152600f84015461016084015260109093015416151561018090910152909150600061123d89613674565b61010084015190915080821190821060008261126957838661010001516112649190615c35565b611279565b6101008601516112799085615c35565b90506000866101000151828860a001516112939190615add565b61129d9190615afc565b905060008760c001516112b057836112b2565b845b60808901519091508115611330576000620186a0600c548b61010001516112d99190615add565b6112e39190615afc565b85101590506000600b548b60200151600001516113009190615b1e565b4210159050818061130e5750805b156113245761131d8584615b1e565b9250611329565b600099505b505061134d565b808311156113405750600061134d565b61134a8382615c35565b90505b959e959d50909b5099509397509195505050505050565b61136c6140c1565b60048054911515600160a01b0260ff60a01b19909216919091179055565b6060601a6000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611405578382906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906113bf565b505050509050919050565b6114186140c1565b60008160ff16116114535760405162461bcd60e51b81526020600482015260056024820152646d696e203160d81b6044820152606401610b85565b6006805460ff191660ff92909216919091179055565b600081156114775781611479565b425b9150600080848154811061148f5761148f615a77565b90600052602060002090600702016040518060e00160405290816000820180546114b890615a8d565b80601f01602080910402602001604051908101604052809291908181526020018280546114e490615a8d565b80156115315780601f1061150657610100808354040283529160200191611531565b820191906000526020600020905b81548152906001019060200180831161151457829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201805480602002602001604051908101604052809291908181526020016000905b828210156115ec576000848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b900461ffff1683850152600190810154918301919091529083529092019101611591565b50505050815250509050600181604001511015801561161057506001816060015110155b156116ae576004805460405163045f145760e31b81529182018590526000916001600160a01b03909116906322f8a2b890602401602060405180830381865afa158015611661573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116859190615c48565b9050816040015181108061169c5750816060015181115b156116ac5760009250505061176b565b505b600181608001511015806116c7575060018160a0015110155b156117655760048054604051631f11cf0d60e11b81529182018590526000916001600160a01b0390911690633e239e1a90602401602060405180830381865afa158015611718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173c9190615c48565b9050816080015181108061175357508160a0015181115b156117635760009250505061176b565b505b60019150505b92915050565b6000805b601b54811015611887576000601b828154811061179457611794615a77565b9060005260206000200154905060006117ac82611b22565b905060006117b983610dc9565b905081806117c45750805b15611871576117d483600161411b565b846117de81615c61565b955050811561181f576040518381527feb7f91469bb290996747407607c0d2bf6b0d11afb8d5ada15dd2269709879eaf9060200160405180910390a1611859565b8015611859576040518381527fb2f224dd9601ae969b3a64ea0493482e0eead1fa818bc855679c3ad666ea1fef9060200160405180910390a15b60065460ff9081169086161061187157505050611887565b505050808061187f90615b31565b915050611775565b50505050565b6118956140c1565b600a805460ff909216620100000262ff000019909216919091179055565b6118bb6140c1565b6102588110156118f75760405162461bcd60e51b81526020600482015260076024820152666d696e2031306d60c81b6044820152606401610b85565b600f55565b6000806000808490506000816001600160a01b03166358303b106040518163ffffffff1660e01b8152600401602060405180830381865afa158015611945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119699190615c80565b90506000826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119cf9190615c9d565b9050600080846001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015611a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a369190615cd6565b50505091509150838284600a611a4c9190615c26565b611a5e90670de0b6b3a7640000615afc565b611a689084615add565b97509750975050505050509193909250565b6002546040516331a9108f60e11b81526004810185905284916001600160a01b031690636352211e90602401602060405180830381865afa158015611ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae79190615d26565b6001600160a01b0316336001600160a01b031614611b175760405162461bcd60e51b8152600401610b8590615d43565b6118878484846143a0565b6000818152601760209081526040808320815181546101c0948102820185019093526101a08101838152859491938492849190879085015b82821015611c0157600084815260209081902060408051610100810182526003860290920180546001600160a01b03811660a0850190815261ffff600160a01b909204821660c086015260018084015460e0870152908552600290920154808216858701526001600160501b03620100008204811694860194909452600160601b81049091166060850152600160701b900490911660808301529083529092019101611b5a565b505050908252506040805160c0808201835260018501548252600285015460208381019190915260038601548385015260048601546060808501919091526005870154608080860191909152600688015460a0808701919091529287019490945260078701546001600160a01b031694860194909452600886015493850193909352600985015491840191909152600a84015491830191909152600b83015460ff80821615159284019290925261ffff610100918290041660e0840152600c84015490830152600d830154610120830152600e830154610140830152600f83015461016083015260109092015490911615156101809091015290506000611d0784612178565b9050600080611d1586613030565b915091506000806000611d2789611043565b509350509250925060008760c00151611d505786886101000151611d4b9190615b1e565b611d61565b86886101000151611d619190615c35565b905060008860c00151611d775781851015611d7c565b818511155b9050600083158015611d97575084611d94888a615b1e565b10155b90508180611da25750805b9c9b505050505050505050505050565b601d8181548110611dc257600080fd5b600091825260209091200154905081565b611ddb6140c1565b6064611deb620186a06001615add565b611df59190615afc565b8110611e2c5760405162461bcd60e51b81526020600482015260066024820152656d617820312560d01b6044820152606401610b85565b601055565b611e396140c1565b6064611e49620186a06003615add565b611e539190615afc565b8110611e8a5760405162461bcd60e51b81526020600482015260066024820152656d617820332560d01b6044820152606401610b85565b600c55565b6002546040516331a9108f60e11b81526004810184905283916001600160a01b031690636352211e90602401602060405180830381865afa158015611ed8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611efc9190615d26565b6001600160a01b0316336001600160a01b031614611f2c5760405162461bcd60e51b8152600401610b8590615d43565b61103e8383614463565b6000606060005b601b54811015611fa3576000601b8281548110611f5c57611f5c615a77565b90600052602060002001549050611f7281611b22565b80611f815750611f8181610dc9565b15611f90576001935050611fa3565b5080611f9b81615b31565b915050611f3d565b509250929050565b611fb36140c1565b611fbd6000614521565b565b611fc76140c1565b6001600160a01b03821660009081526005602052604090205481151560ff9091161515036120205760405162461bcd60e51b8152600401610b85906020808252600490820152635345543360e01b604082015260600190565b6001600160a01b03919091166000908152600560205260409020805460ff1916911515919091179055565b6002546040516331a9108f60e11b81526004810184905283916001600160a01b031690636352211e90602401602060405180830381865afa158015612094573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b89190615d26565b6001600160a01b0316336001600160a01b0316146120e85760405162461bcd60e51b8152600401610b8590615d43565b61103e8383614573565b6120fa6140c1565b60065460405163a9059cbb60e01b81526101009091046001600160a01b031660048201819052602482018390529063a9059cbb906044016020604051808303816000875af1158015612150573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121749190615d6e565b5050565b6000818152601760205260408120600b810154600c9091015461010090910461ffff16906121a7906009615add565b61176b9190615afc565b6060600880548060200260200160405190810160405280929190818152602001828054801561220957602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121eb575b5050505050905090565b6000818154811061222357600080fd5b906000526020600020906007020160009150905080600001805461224690615a8d565b80601f016020809104026020016040519081016040528092919081815260200182805461227290615a8d565b80156122bf5780601f10612294576101008083540402835291602001916122bf565b820191906000526020600020905b8154815290600101906020018083116122a257829003601f168201915b5050505050908060010154908060020154908060030154908060040154908060050154905086565b6122f281600061411b565b50565b6122fd6140c1565b81811561230a5781612372565b6040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa15801561234e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123729190615c48565b91506000821161238157600080fd5b806001600160a01b031663a9059cbb6123a26001546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303816000875af11580156123ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118879190615d6e565b60606000805480602002602001604051908101604052809291908181526020016000905b828210156125b557838290600052602060002090600702016040518060e001604052908160008201805461246a90615a8d565b80601f016020809104026020016040519081016040528092919081815260200182805461249690615a8d565b80156124e35780601f106124b8576101008083540402835291602001916124e3565b820191906000526020600020905b8154815290600101906020018083116124c657829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201805480602002602001604051908101604052809291908181526020016000905b8282101561259e576000848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b900461ffff1683850152600190810154918301919091529083529092019101612543565b505050508152505081526020019060010190612437565b50505050905090565b600454600160a01b900460ff166126025760405162461bcd60e51b8152602060048201526008602482015267111254d05093115160c21b6044820152606401610b85565b600054851061263c5760405162461bcd60e51b81526020600482015260066024820152650929cac9288b60d31b6044820152606401610b85565b600a8361ffff161015801561265b5750600a5461ffff90811690841611155b6126905760405162461bcd60e51b8152600401610b85906020808252600490820152634c45563160e01b604082015260600190565b61269b856000611469565b6126d15760405162461bcd60e51b8152602060048201526007602482015266494e444f4f423160c81b6044820152606401610b85565b6001600160a01b03861615806126f957506006546001600160a01b0387811661010090920416145b8061271c57506001600160a01b03861660009081526007602052604090205460ff165b6127545760405162461bcd60e51b8152602060048201526009602482015268504f53544f4b454e3160b81b6044820152606401610b85565b60006001600160a01b0387161561276b578661277d565b60065461010090046001600160a01b03165b6040516370a0823160e01b815233600482015290915085906001600160a01b038316906370a0823190602401602060405180830381865afa1580156127c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ea9190615c48565b10156128215760405162461bcd60e51b8152600401610b859060208082526004908201526342414c3160e01b604082015260600190565b6002546040516335313c2160e11b81523360048201526000916001600160a01b031690636a627842906024016020604051808303816000875af115801561286c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128909190615c48565b6040516323b872dd60e01b8152336004820152306024820152604481018890529091506001600160a01b038316906323b872dd906064016020604051808303816000875af11580156128e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061290a9190615d6e565b50600061291b878761ffff16614680565b905060006129298289615c35565b9050816011600082825461293d9190615b1e565b925050819055506000808a8154811061295857612958615a77565b90600052602060002090600702016040518060e001604052908160008201805461298190615a8d565b80601f01602080910402602001604051908101604052809291908181526020018280546129ad90615a8d565b80156129fa5780601f106129cf576101008083540402835291602001916129fa565b820191906000526020600020905b8154815290600101906020018083116129dd57829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201805480602002602001604051908101604052809291908181526020016000905b82821015612ab5576000848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b900461ffff1683850152600190810154918301919091529083529092019101612a5a565b5050509152505060008581526017602052604081209192505b8260c0015151811015612c585760008360c001518281518110612af357612af3615a77565b60200260200101519050600080612b0d83600001516118fc565b5091509150846000016040518060a001604052808860c001518781518110612b3757612b37615a77565b602090810291909101810151825261ffff958616828201526001600160501b03948516604080840191909152600060608085018290526080948501829052865460018181018955978352918490208651805160039094029091018054828701518c16600160a01b026001600160b01b03199091166001600160a01b0390951694909417939093178355830151968201969096559184015160029092018054918501519585015194909301518616600160701b0269ffffffffffffffffffff60701b19948816600160601b02949094166bffffffffffffffffffffffff60601b199590961662010000026bffffffffffffffffffffffff1990911691909616179490941791909116919091171790555080612c5081615b31565b915050612ace565b506000612c648c610ba6565b600087815260186020526040902080546001600160a01b0319163317905542600184015560028301869055600983018590559050600a612ca861ffff8c1686615add565b612cb29190615afc565b600a830155600b8201805462ffffff19168a151562ffff0019161761010061ffff8d1602179055600c82018190556007820180546001600160a01b0319166001600160a01b038916179055601b80546000888152601c60205260408120829055600182018355919091527f3ad8aa4f87544323a9d1e5dd902f40c356527a7955687113db5f9a85ad579dc101869055612d4a866146ff565b8715612d5a57612d5a8689614573565b60408051828152602081018690528a15158183015261ffff8c1660608201529051339188917f7851a428332e40237ac34a5efd508d9bbff0fb057da46bf99e1bd1b5c4adf6719181900360800190a350505050505050505050505050565b612dc06140c1565b6064612dd0620186a0600a615add565b612dda9190615afc565b8110612e125760405162461bcd60e51b81526020600482015260076024820152666d61782031302560c81b6044820152606401610b85565b600e55565b6000818152601760209081526040808320805482518185028101850190935280835260609493849084015b82821015612ee957600084815260209081902060408051610100810182526003860290920180546001600160a01b03811660a0850190815261ffff600160a01b909204821660c086015260018084015460e0870152908552600290920154808216858701526001600160501b03620100008204811694860194909452600160601b81049091166060850152600160701b900490911660808301529083529092019101612e42565b50505060008581526017602052604081205492935091905067ffffffffffffffff811115612f1957612f19615762565b604051908082528060200260200182016040528015612f42578160200160208202803683370190505b50905060005b8251811015610dc157828181518110612f6357612f63615a77565b60200260200101516000015160000151828281518110612f8557612f85615a77565b6001600160a01b039092166020928302919091019091015280612fa781615b31565b915050612f48565b601b8181548110611dc257600080fd5b612fc76140c1565b620151808111156130075760405162461bcd60e51b815260206004820152600a6024820152696d61782031206461797360b01b6044820152606401610b85565b600b55565b6130146140c1565b6001600160a01b03909116600090815260166020526040902055565b6002546040516331a9108f60e11b815260048101839052600091829182916001600160a01b031690636352211e90602401602060405180830381865afa15801561307e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a29190615d26565b90506000806130b083614a91565b600e546000898152601760205260408120600a01549395509193509091620186a0916130db91615add565b6130e59190615afc565b6010546000898152601760205260408120600a015492935091620186a09161310c91615add565b6131169190615afc565b600f5460008a815260176020526040812060010154929350916131399042615c35565b6131439084615add565b61314d9190615afc565b9050841561319857836131608685615add565b61316a9190615afc565b6131749084615c35565b9250836131818683615add565b61318b9190615afc565b6131959082615c35565b90505b91989197509095505050505050565b6131af6140c1565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b601a60205281600052604060002081815481106131ed57600080fd5b600091825260209091206002909102018054600190910154909250905082565b6060601d80548060200260200160405190810160405280929190818152602001828054801561220957602002820191906000526020600020905b815481526020019060010190808311613247575050505050905090565b3360009081526005602052604090205460ff166132b35760405162461bcd60e51b815260206004820152600d60248201526c6f6e6c7920736574746c65727360981b6044820152606401610b85565b6000838152601760205260409020601081015460ff16156132ff5760405162461bcd60e51b8152600401610b85906020808252600490820152635345543160e01b604082015260600190565b600081600801541161333c5760405162461bcd60e51b8152600401610b859060208082526004908201526329a2aa1960e11b604082015260600190565b60108101805460ff19166001179055600581018390556006810182905560078101546040805163313ce56760e01b815290516000926001600160a01b03169163313ce5679160048281019260209291908290030181865afa1580156133a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133c99190615c9d565b6133d490600a615c26565b8385600660019054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613429573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061344d9190615c9d565b61345890600a615c26565b85600801546134679190615add565b6134719190615add565b61347b9190615afc565b6134859190615afc565b6006546000878152601960205260409081902054905163a9059cbb60e01b81526001600160a01b03918216600482015260248101849052929350610100909104169063a9059cbb906044016020604051808303816000875af11580156134ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135139190615d6e565b506000858152601e6020526040812054601d805491929161353690600190615c35565b8154811061354657613546615a77565b6000918252602080832090910154898352601e9091526040808320839055818352909120839055601d805491925082918490811061358657613586615a77565b600091825260209091200155601d8054806135a3576135a3615d8b565b600190038181906000526020600020016000905590557f4c246f6c8d41233463bbb11c80907ea3f18c0b7c101910bfa5a599f65cacab4f87848888604051613604949392919093845260208401929092526040830152606082015260800190565b60405180910390a150505050505050565b61361d6140c1565b606461362d620186a0600a615add565b6136379190615afc565b811061366f5760405162461bcd60e51b81526020600482015260076024820152666d61782031302560c81b6044820152606401610b85565b600d55565b6000818152601760209081526040808320815181546101c0948102820185019093526101a08101838152859491938492849190879085015b8282101561375357600084815260209081902060408051610100810182526003860290920180546001600160a01b03811660a0850190815261ffff600160a01b909204821660c086015260018084015460e0870152908552600290920154808216858701526001600160501b03620100008204811694860194909452600160601b81049091166060850152600160701b9004909116608083015290835290920191016136ac565b505050908252506040805160c0808201835260018501548252600285015460208381019190915260038601548385015260048601546060808501919091526005870154608080860191909152600688015460a0808701919091529287019490945260078701546001600160a01b031694860194909452600886015493850193909352600985015491840191909152600a84015491830191909152600b83015460ff80821615159284019290925261ffff610100918290041660e0840152600c84015490830152600d830154610120830152600e830154610140830152600f83015461016083015260109092015490911615156101809091015280515190915060009067ffffffffffffffff81111561386d5761386d615762565b604051908082528060200260200182016040528015613896578160200160208202803683370190505b509050600082600001515167ffffffffffffffff8111156138b9576138b9615762565b6040519080825280602002602001820160405280156138e2578160200160208202803683370190505b50905060005b83515181101561399357835180518290811061390657613906615a77565b6020026020010151600001516000015183828151811061392857613928615a77565b6001600160a01b0390921660209283029190910190910152835180518290811061395457613954615a77565b6020026020010151600001516040015182828151811061397657613976615a77565b60209081029190910101528061398b81615b31565b9150506138e8565b5061399e8282613d6c565b95945050505050565b6139af6140c1565b601b54156139ea5760405162461bcd60e51b81526020600482015260086024820152671350525390d3d31360c21b6044820152606401610b85565b600680546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b613a1a6140c1565b6001600160a01b03821660009081526007602052604090205481151560ff909116151503613a795760405162461bcd60e51b815260206004820152600c60248201526b6368616e676520737461746560a01b6044820152606401610b85565b6001600160a01b0382166000908152600760205260409020805460ff19168215801591909117909155613b0657600880546001600160a01b0384166000818152600960205260408120839055600183018455929092527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b03191690911790555050565b6001600160a01b0382166000908152600960205260408120805491905560088054613b3390600190615c35565b81548110613b4357613b43615a77565b600091825260209091200154600880546001600160a01b039092169183908110613b6f57613b6f615a77565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506008805480613bae57613bae615d8b565b600082815260209020810160001990810180546001600160a01b0319169055019055505050565b613bdd6140c1565b6001600160a01b038116613c425760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b85565b6122f281614521565b613c536140c1565b60008054613c6390600190615c35565b81548110613c7357613c73615a77565b906000526020600020906007020160008281548110613c9457613c94615a77565b6000918252602090912060079091020180613caf8382615def565b5060018201548160010155600282015481600201556003820154816003015560048201548160040155600582015481600501556006820181600601908054613cf8929190615098565b509050506000805480613d0d57613d0d615d8b565b60008281526020812060001990920191600783020190613d2d8282615134565b60018201600090556002820160009055600382016000905560048201600090556005820160009055600682016000613d65919061516e565b5050905550565b60008151835114613d7c57600080fd5b6000805b8451811015610dc1576000613dad868381518110613da057613da0615a77565b60200260200101516118fc565b925050508551600114613df757670de0b6b3a7640000858381518110613dd557613dd5615a77565b602002602001015182613de89190615add565b613df29190615afc565b613df9565b805b613e039084615b1e565b9250508080613e1190615b31565b915050613d80565b613e216140c1565b60008251118015613e33575080518251145b613e6a5760405162461bcd60e51b815260206004820152600860248201526739b0b6b2903632b760c11b6044820152606401610b85565b600080546001810182559080526007027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5630180613ea78582615ecc565b5060005b835181101561406f576000848281518110613ec857613ec8615a77565b602002602001015190506000613edd826118fc565b9250505060008111613f215760405162461bcd60e51b815260206004820152600d60248201526c696e76616c69642070726f787960981b6044820152606401610b85565b8551600114613f4957848381518110613f3c57613f3c615a77565b6020026020010151613f4c565b60005b61ffff16846001016000828254613f639190615b1e565b92505081905550836006016040518060600160405280846001600160a01b03168152602001878681518110613f9a57613f9a615a77565b602002602001015161ffff1681526020018851600114613fff5783613fc86002670de0b6b3a7640000615c26565b898881518110613fda57613fda615a77565b602002602001015161ffff16613ff09190615add565b613ffa9190615afc565b614002565b60005b90528154600181810184556000938452602093849020835160029093020180549484015161ffff16600160a01b026001600160b01b03199095166001600160a01b03909316929092179390931781556040909101519101555081905061406781615b31565b915050613eab565b5050505050565b61407e6140c1565b600080868154811061409257614092615a77565b600091825260209091206007909102016002810195909555506003840192909255600483015560059091015550565b6001546001600160a01b03163314611fbd5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b85565b60008281526017602052604080822060025491516331a9108f60e11b8152600481018690529092916001600160a01b031690636352211e90602401602060405180830381865afa158015614173573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141979190615d26565b905082806141ad5750336001600160a01b038216145b6141e15760405162461bcd60e51b81526020600482015260056024820152644f574e4c5160d81b6044820152606401610b85565b60025460405163c3738f3f60e01b8152600481018690526001600160a01b039091169063c3738f3f90602401602060405180830381865afa15801561422a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061424e9190615d6e565b6142835760405162461bcd60e51b8152602060048201526006602482015265434c4f53453160d01b6044820152606401610b85565b61428d8482614b24565b61429684614c50565b61429f84614cfa565b6142a884614dbb565b600254604051630852cd8d60e31b8152600481018690526001600160a01b03909116906342966c6890602401600060405180830381600087803b1580156142ee57600080fd5b505af1158015614302573d6000803e3d6000fd5b5050506000858152601960205260409081902080546001600160a01b0385166001600160a01b03199091168117909155600c850154600d860154600e870154600f880154945193955089947fad61fdefcf969920b58ee3fc753c769d85f23f36b446cf737c0c5e7dcf840a6e94614392949392919093845260208401929092526040830152606082015260800190565b60405180910390a350505050565b600081116143d65760405162461bcd60e51b81526020600482015260036024820152620544f360ec1b6044820152606401610b85565b6000838152601a602052604081208054849081106143f6576143f6615a77565b90600052602060002090600202019050600081600001548260010154109050806144235781548311614428565b815483105b61445a5760405162461bcd60e51b8152602060048201526003602482015262544f3360e81b6044820152606401610b85565b50600101555050565b6000828152601a60205260409020805461447f90600190615c35565b8154811061448f5761448f615a77565b9060005260206000209060020201601a600084815260200190815260200160002082815481106144c1576144c1615a77565b6000918252602080832084546002909302019182556001938401549390910192909255838152601a909152604090208054806144ff576144ff615d8b565b6000828152602081206002600019909301928302018181556001015590555050565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600081116145a95760405162461bcd60e51b81526020600482015260036024820152620544f360ec1b6044820152606401610b85565b600a546000838152601a60205260409020546201000090910460ff16116145f85760405162461bcd60e51b8152602060048201526003602482015262544f3160e81b6044820152606401610b85565b600061460383613674565b905081810361463a5760405162461bcd60e51b81526020600482015260036024820152622a279960e91b6044820152606401610b85565b6000928352601a60209081526040808520815180830190925292815280820193845282546001818101855593865291909420935160029091029093019283559051910155565b600080600a61468f8486615add565b6146999190615afc565b90506000620186a0600d54836146af9190615add565b6146b99190615afc565b90506000806146c733614a91565b909250905081156146f457806146dd8385615add565b6146e79190615afc565b6146f19084615c35565b92505b509095945050505050565b6000818152601760209081526040808320815181546101c0948102820185019093526101a08101838152909391928492849190879085015b828210156147de57600084815260209081902060408051610100810182526003860290920180546001600160a01b03811660a0850190815261ffff600160a01b909204821660c086015260018084015460e0870152908552600290920154808216858701526001600160501b03620100008204811694860194909452600160601b81049091166060850152600160701b900490911660808301529083529092019101614737565b505050908252506040805160c0808201835260018501548252600285015460208381019190915260038601548385015260048601546060808501919091526005870154608080860191909152600688015460a0808701919091529287019490945260078701546001600160a01b031694860194909452600886015493850193909352600985015491840191909152600a84015491830191909152600b83015460ff80821615158385015261ffff610100928390041660e0850152600c85015491840191909152600d840154610120840152600e840154610140840152600f8401546101608401526010909301549092161515610180909101528101519091501561491e5760a08101516040808301516001600160a01b0316600090815260146020529081208054909190614913908490615b1e565b909155506149559050565b60a08101516040808301516001600160a01b031660009081526015602052908120805490919061494f908490615b1e565b90915550505b6040808201516001600160a01b03166000908152601660205220541561217457604080820180516001600160a01b039081166000908152601560209081528482205493519092168152601490915291822054116149ee57604080830180516001600160a01b039081166000908152601460209081528482205493519092168152601590915291909120546149e99190615c35565b614a2b565b604080830180516001600160a01b03908116600090815260156020908152848220549351909216815260149091529190912054614a2b9190615c35565b6040808401516001600160a01b031660009081526016602052205490915081111561103e5760405162461bcd60e51b81526020600482015260166024820152751b585e0818dbdb1b185d195c985b081c995858da195960521b6044820152606401610b85565b60035460009081906001600160a01b0316614aae57600080614b1b565b60035460405163a310e73960e01b81526001600160a01b0385811660048301529091169063a310e739906024016040805180830381865afa158015614af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b1b9190615f84565b91509150915091565b60008281526017602052604081209080614b3d85613030565b90925090506000614b4e8284615b1e565b90508060116000828254614b629190615b1e565b909155506000905080808080614b778b611043565b945094509450945094508115614baa578015614ba5578260126000828254614b9f9190615b1e565b90915550505b614bc2565b8260136000828254614bbc9190615b1e565b90915550505b838611614bd857614bd38685615c35565b614bdb565b60005b9350614be88b8b86614e66565b4260038a015560048901869055600d8901859055818015614c065750805b614c11576000614c13565b825b600e8a015581614c385788600901548311614c2e5782614c3b565b8860090154614c3b565b60005b89600f01819055505050505050505050505050565b6000818152601c6020526040812054601b8054919291614c7290600190615c35565b81548110614c8257614c82615a77565b6000918252602080832090910154858352601c9091526040808320839055818352909120839055601b8054919250829184908110614cc257614cc2615a77565b600091825260209091200155601b805480614cdf57614cdf615d8b565b60019003818190600052602060002001600090559055505050565b6000818152601760205260408120905b815481101561103e576000826000018281548110614d2a57614d2a615a77565b60009182526020822060039091020180549092508190614d52906001600160a01b03166118fc565b50600290940180546001600160501b03909516600160701b0269ffffffffffffffffffff60701b1961ffff909316600160601b02929092166bffffffffffffffffffffffff60601b19909516949094171790925550819050614db381615b31565b915050614d0a565b6000818152601760205260409020600b015460ff1615614e1f576000818152601760209081526040808320600a8101546007909101546001600160a01b0316845260149092528220805491929091614e14908490615c35565b909155506122f29050565b6000818152601760209081526040808320600a8101546007909101546001600160a01b0316845260159092528220805491929091614e5e908490615c35565b909155505050565b600083815260176020526040902081156150835760065460078201546001600160a01b036101009092048216911603614f285760108101805460ff19166001179055600781015460405163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529091169063a9059cbb906044015b6020604051808303816000875af1158015614efe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f229190615d6e565b50611887565b8060090154821115615039576007810154600982015460405163a9059cbb60e01b81526001600160a01b038681166004830152602482019290925291169063a9059cbb906044016020604051808303816000875af1158015614f8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614fb29190615d6e565b506009810154614fc29083615c35565b6008820155601d80546000868152601e60205260408082208390556001830184559281527f6d4407e7be21f808e6509aa9fa9143369579dd7d760fe20a2c09680fc146134f909101869055905185917f1cf3a4d81180ed8c843ad38f7adadb6357459df6a134d14614cf7ca32dbee42191a2611887565b60108101805460ff19166001179055600781015460405163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529091169063a9059cbb90604401614edf565b60108101805460ff1916600117905550505050565b8280548282559060005260206000209060020281019282156151245760005260206000209160020282015b8281111561512457825482546001600160a01b039091166001600160a01b031982168117845584546001600160b01b031990921617600160a01b9182900461ffff1690910217825560018084015490830155600292830192909101906150c3565b5061513092915061518b565b5090565b50805461514090615a8d565b6000825580601f10615150575050565b601f0160209004906000526020600020908101906122f291906151b1565b50805460008255600202906000526020600020908101906122f291905b5b808211156151305780546001600160b01b03191681556000600182015560020161518c565b5b8082111561513057600081556001016151b2565b61ffff811681146122f257600080fd5b6000602082840312156151e857600080fd5b81356151f3816151c6565b9392505050565b60006020828403121561520c57600080fd5b5035919050565b6001600160a01b03811681146122f257600080fd5b60006020828403121561523a57600080fd5b81356151f381615213565b80151581146122f257600080fd5b60006020828403121561526557600080fd5b81356151f381615245565b602080825282518282018190526000919060409081850190868401855b828110156152b25781518051855286015186850152928401929085019060010161528d565b5091979650505050505050565b60ff811681146122f257600080fd5b6000602082840312156152e057600080fd5b81356151f3816152bf565b600080604083850312156152fe57600080fd5b50508035926020909101359150565b6000806020838503121561532057600080fd5b823567ffffffffffffffff8082111561533857600080fd5b818501915085601f83011261534c57600080fd5b81358181111561535b57600080fd5b86602082850101111561536d57600080fd5b60209290920196919550909350505050565b60008060006060848603121561539457600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b818110156153d1576020818501810151868301820152016153b5565b506000602082860101526020601f19601f83011685010191505092915050565b821515815260406020820152600061540c60408301846153ab565b949350505050565b6000806040838503121561542757600080fd5b823561543281615213565b9150602083013561544281615245565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561548e5783516001600160a01b031683529284019291840191600101615469565b50909695505050505050565b60c0815260006154ad60c08301896153ab565b60208301979097525060408101949094526060840192909252608083015260a090910152919050565b6000610220820190508d51825260208e0151602083015260408e0151604083015260608e0151606083015260808e0151608083015260a08e015160a083015261552a60c083018e6001600160a01b03169052565b8b60e08301528a6101008301528961012083015261554d61014083018a15159052565b61ffff881661016083015286610180830152856101a0830152846101c0830152836101e083015261558361020083018415159052565b9d9c50505050505050505050505050565b600080604083850312156155a757600080fd5b82356155b281615213565b946020939093013593505050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b848110156156b457603f198a8503018652825160e0815181875261560e828801826153ab565b838c0151888d01528a8401518b890152606080850151818a0152608080860151908a015260a080860151908a015260c094850151898303958a01959095528451808352948d0194879450909250908c01905b8084101561569e57845180516001600160a01b031683528d81015161ffff168e8401528c01518c830152938c01936001939093019290820190615660565b50988b01989650505092880192506001016155e8565b50919998505050505050505050565b60008060008060008060c087890312156156dc57600080fd5b86356156e781615213565b955060208701359450604087013593506060870135615705816151c6565b9250608087013561571581615245565b8092505060a087013590509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561548e57835183529284019291840191600101615746565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156157a1576157a1615762565b604052919050565b600067ffffffffffffffff8211156157c3576157c3615762565b5060051b60200190565b600082601f8301126157de57600080fd5b813560206157f36157ee836157a9565b615778565b82815260059290921b8401810191818101908684111561581257600080fd5b8286015b8481101561583657803561582981615213565b8352918301918301615816565b509695505050505050565b6000806040838503121561585457600080fd5b823567ffffffffffffffff8082111561586c57600080fd5b615878868387016157cd565b935060209150818501358181111561588f57600080fd5b85019050601f810186136158a257600080fd5b80356158b06157ee826157a9565b81815260059190911b820183019083810190888311156158cf57600080fd5b928401925b828410156158ed578335825292840192908401906158d4565b80955050505050509250929050565b600082601f83011261590d57600080fd5b8135602061591d6157ee836157a9565b82815260059290921b8401810191818101908684111561593c57600080fd5b8286015b84811015615836578035615953816151c6565b8352918301918301615940565b60008060006060848603121561597557600080fd5b833567ffffffffffffffff8082111561598d57600080fd5b818601915086601f8301126159a157600080fd5b81356020828211156159b5576159b5615762565b6159c7601f8301601f19168201615778565b82815289828487010111156159db57600080fd5b82828601838301376000928101820192909252909550860135915080821115615a0357600080fd5b615a0f878388016157cd565b93506040860135915080821115615a2557600080fd5b50615a32868287016158fc565b9150509250925092565b600080600080600060a08688031215615a5457600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680615aa157607f821691505b602082108103615ac157634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615615af757615af7615ac7565b500290565b600082615b1957634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561176b5761176b615ac7565b600060018201615b4357615b43615ac7565b5060010190565b600181815b80851115611fa3578160001904821115615b6b57615b6b615ac7565b80851615615b7857918102915b93841c9390800290615b4f565b600082615b945750600161176b565b81615ba15750600061176b565b8160018114615bb75760028114615bc157615bdd565b600191505061176b565b60ff841115615bd257615bd2615ac7565b50506001821b61176b565b5060208310610133831016604e8410600b8410161715615c00575081810a61176b565b615c0a8383615b4a565b8060001904821115615c1e57615c1e615ac7565b029392505050565b60006151f360ff841683615b85565b8181038181111561176b5761176b615ac7565b600060208284031215615c5a57600080fd5b5051919050565b600060ff821660ff8103615c7757615c77615ac7565b60010192915050565b600060208284031215615c9257600080fd5b81516151f3816151c6565b600060208284031215615caf57600080fd5b81516151f3816152bf565b80516001600160501b0381168114615cd157600080fd5b919050565b600080600080600060a08688031215615cee57600080fd5b615cf786615cba565b9450602086015193506040860151925060608601519150615d1a60808701615cba565b90509295509295909350565b600060208284031215615d3857600080fd5b81516151f381615213565b60208082526011908201527036bab9ba1037bbb7103837b9b4ba34b7b760791b604082015260600190565b600060208284031215615d8057600080fd5b81516151f381615245565b634e487b7160e01b600052603160045260246000fd5b601f82111561103e57600081815260208120601f850160051c81016020861015615dc85750805b601f850160051c820191505b81811015615de757828155600101615dd4565b505050505050565b818103615dfa575050565b615e048254615a8d565b67ffffffffffffffff811115615e1c57615e1c615762565b615e3081615e2a8454615a8d565b84615da1565b6000601f821160018114615e645760008315615e4c5750848201545b600019600385901b1c1916600184901b17845561406f565b600085815260209020601f19841690600086815260209020845b83811015615e9e5782860154825560019586019590910190602001615e7e565b5085831015615ebc5781850154600019600388901b60f8161c191681555b5050505050600190811b01905550565b815167ffffffffffffffff811115615ee657615ee6615762565b615ef481615e2a8454615a8d565b602080601f831160018114615f295760008415615f115750858301515b600019600386901b1c1916600185901b178555615de7565b600085815260208120601f198616915b82811015615f5857888601518255948401946001909101908401615f39565b5085821015615ebc57939096015160001960f8600387901b161c19169092555050600190811b01905550565b60008060408385031215615f9757600080fd5b50508051602090910151909290915056fea164736f6c6343000810000a60806040526032600f553480156200001657600080fd5b50604051620026c1380380620026c1833981016040819052620000399162000154565b60408051808201825260208082527f5969656c64696669636174696f6e2050657270657475616c2046757475726573818301528251808401909352600583526438332ca22360d91b90830152906000620000948382620002b8565b506001620000a38282620002b8565b505050620000c0620000ba620000e860201b60201c565b620000ec565b600d620000ce8282620002b8565b5050600b80546001600160a01b0319163317905562000384565b3390565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600060208083850312156200016857600080fd5b82516001600160401b03808211156200018057600080fd5b818501915085601f8301126200019557600080fd5b815181811115620001aa57620001aa6200013e565b604051601f8201601f19908116603f01168101908382118183101715620001d557620001d56200013e565b816040528281528886848701011115620001ee57600080fd5b600093505b82841015620002125784840186015181850187015292850192620001f3565b600086848301015280965050505050505092915050565b600181811c908216806200023e57607f821691505b6020821081036200025f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002b357600081815260208120601f850160051c810160208610156200028e5750805b601f850160051c820191505b81811015620002af578281556001016200029a565b5050505b505050565b81516001600160401b03811115620002d457620002d46200013e565b620002ec81620002e5845462000229565b8462000265565b602080601f8311600181146200032457600084156200030b5750858301515b600019600386901b1c1916600185901b178555620002af565b600085815260208120601f198616915b82811015620003555788860151825594840194600190910190840162000334565b5085821015620003745787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61232d80620003946000396000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80636a62784211610125578063afd50d8f116100ad578063c87b56dd1161007c578063c87b56dd146104c1578063e8a3d485146104d4578063e985e9c5146104dc578063f2fde38b14610518578063ffa801361461052b57600080fd5b8063afd50d8f14610468578063b6b8194014610488578063b88d4fde1461049b578063c3738f3f146104ae57600080fd5b80637974e46a116100f45780637974e46a146104215780638da5cb5b1461042957806395d89b411461043a578063a22cb46514610442578063ad2f852a1461045557600080fd5b80636a627842146103d357806370a08231146103e6578063715018a6146103f957806376772cf81461040157600080fd5b8063274de61e116101a857806342842e0e1161017757806342842e0e1461037457806342966c68146103875780634f6ccce71461039a57806355f804b3146103ad5780636352211e146103c057600080fd5b8063274de61e146102fc5780632a55205a1461031c5780632d88931b1461034e5780632f745c591461036157600080fd5b8063095ea7b3116101ef578063095ea7b31461029e57806310bd14fe146102b157806318160ddd146102c457806320e3fa50146102d657806323b872dd146102e957600080fd5b806301ffc9a71461022157806306d254da1461024957806306fdde031461025e578063081812fc14610273575b600080fd5b61023461022f366004611c16565b61054b565b60405190151581526020015b60405180910390f35b61025c610257366004611c51565b61055c565b005b6102666105ae565b6040516102409190611cbc565b610286610281366004611ccf565b610640565b6040516001600160a01b039091168152602001610240565b61025c6102ac366004611ce8565b610667565b600b54610286906001600160a01b031681565b6008545b604051908152602001610240565b6102c86102e4366004611ce8565b610781565b61025c6102f7366004611d12565b6107b2565b6102c861030a366004611ccf565b60116020526000908152604090205481565b61032f61032a366004611d4e565b6107e3565b604080516001600160a01b039093168352602083019190915201610240565b61025c61035c366004611c51565b61081d565b6102c861036f366004611ce8565b610847565b61025c610382366004611d12565b6108dd565b61025c610395366004611ccf565b6108f8565b6102c86103a8366004611ccf565b6109b1565b61025c6103bb366004611dfc565b610a44565b6102866103ce366004611ccf565b610a9a565b6102c86103e1366004611c51565b610afa565b6102c86103f4366004611c51565b610bcc565b61025c610c52565b6102c861040f366004611ccf565b60126020526000908152604090205481565b6102c8610c66565b600a546001600160a01b0316610286565b610266610c76565b61025c610450366004611e45565b610c85565b600e54610286906001600160a01b031681565b6102c8610476366004611ccf565b60136020526000908152604090205481565b61025c610496366004611ccf565b610c94565b61025c6104a9366004611e81565b610ccf565b6102346104bc366004611ccf565b610d07565b6102666104cf366004611ccf565b610d26565b610266610d82565b6102346104ea366004611efd565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b61025c610526366004611c51565b610db0565b61053e610539366004611c51565b610e29565b6040516102409190611f30565b600061055682610e95565b92915050565b610564610eba565b600e80546001600160a01b0319166001600160a01b0383169081179091556040517f0f2a87e68f9d4311c1d18e960f7873198e70403a037237cdd2c583c69cdddf1f90600090a250565b6060600080546105bd90611f74565b80601f01602080910402602001604051908101604052809291908181526020018280546105e990611f74565b80156106365780601f1061060b57610100808354040283529160200191610636565b820191906000526020600020905b81548152906001019060200180831161061957829003601f168201915b5050505050905090565b600061064b82610f14565b506000908152600460205260409020546001600160a01b031690565b600061067282610a9a565b9050806001600160a01b0316836001600160a01b0316036106e45760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610700575061070081336104ea565b6107725760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c000060648201526084016106db565b61077c8383610f73565b505050565b6010602052816000526040600020818154811061079d57600080fd5b90600052602060002001600091509150505481565b6107bc3382610fe1565b6107d85760405162461bcd60e51b81526004016106db90611fae565b61077c838383611060565b600e54600f5460009182916001600160a01b03909116906103e8906108089086612012565b6108129190612047565b915091509250929050565b610825610eba565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b600061085283610bcc565b82106108b45760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b60648201526084016106db565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b61077c83838360405180602001604052806000815250610ccf565b600b546001600160a01b0316331461093f5760405162461bcd60e51b815260206004820152600a6024820152696f6e6c7920706572707360b01b60448201526064016106db565b600061094a82610a9a565b6000838152600260205260409020549091506001600160a01b031661096e57600080fd5b6109778261120d565b6040516001600160a01b0382169083907ff6554c3a5d28e08c120b5a69c7edbaf52f935bd2596a60b8a18e282cd257cddb90600090a35050565b60006109bc60085490565b8210610a1f5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b60648201526084016106db565b60088281548110610a3257610a3261205b565b90600052602060002001549050919050565b610a4c610eba565b600d610a5882826120bf565b5080604051610a67919061217f565b604051908190038120907f199e933997358e1789d8b56ea8c551befeb05ce2fe3fe506199f1230f5a591b490600090a250565b6000818152600260205260408120546001600160a01b0316806105565760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016106db565b600b546000906001600160a01b03163314610b445760405162461bcd60e51b815260206004820152600a6024820152696f6e6c7920706572707360b01b60448201526064016106db565b610b52600c80546001019055565b610b6482610b5f600c5490565b6112bc565b4260126000610b72600c5490565b81526020810191909152604001600020556001600160a01b038216610b96600c5490565b6040517ff3cea5493d790af0133817606f7350a91d7f154ea52eaa79d179d4d231e5010290600090a3600c54610556565b919050565b60006001600160a01b038216610c365760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b60648201526084016106db565b506001600160a01b031660009081526003602052604090205490565b610c5a610eba565b610c6460006112d6565b565b6000610c71600c5490565b905090565b6060600180546105bd90611f74565b610c90338383611328565b5050565b610c9c610eba565b600f81905560405181907f2ad2ae73af42f598ecb723109218def6abfe2e801eb5719ab4acbf9adc91c65d90600090a250565b610cd93383610fe1565b610cf55760405162461bcd60e51b81526004016106db90611fae565b610d01848484846113f6565b50505050565b6000818152600260205260408120546001600160a01b03161515610556565b6000818152600260205260409020546060906001600160a01b0316610d4a57600080fd5b610d52611429565b610d5b83611438565b604051602001610d6c92919061219b565b6040516020818303038152906040529050919050565b6060610d8c611429565b604051602001610d9c91906121da565b604051602081830303815290604052905090565b610db8610eba565b6001600160a01b038116610e1d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106db565b610e26816112d6565b50565b6001600160a01b038116600090815260106020908152604091829020805483518184028101840190945280845260609392830182828015610e8957602002820191906000526020600020905b815481526020019060010190808311610e75575b50505050509050919050565b60006001600160e01b0319821663780e9d6360e01b1480610556575061055682611539565b600a546001600160a01b03163314610c645760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106db565b6000818152600260205260409020546001600160a01b0316610e265760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016106db565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610fa882610a9a565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080610fed83610a9a565b9050806001600160a01b0316846001600160a01b0316148061103457506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b806110585750836001600160a01b031661104d84610640565b6001600160a01b0316145b949350505050565b826001600160a01b031661107382610a9a565b6001600160a01b0316146110d75760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b60648201526084016106db565b6001600160a01b0382166111395760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016106db565b611144838383611589565b61114f600082610f73565b6001600160a01b038316600090815260036020526040812080546001929061117890849061220b565b90915550506001600160a01b03821660009081526003602052604081208054600192906111a690849061221e565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a461077c8383836115a5565b600061121882610a9a565b905061122681600084611589565b611231600083610f73565b6001600160a01b038116600090815260036020526040812080546001929061125a90849061220b565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a4610c90816000846115a5565b610c9082826040518060200160405280600081525061172e565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b0316036113895760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016106db565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b611401848484611060565b61140d84848484611761565b610d015760405162461bcd60e51b81526004016106db90612231565b6060600d80546105bd90611f74565b60608160000361145f5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611489578061147381612283565b91506114829050600a83612047565b9150611463565b60008167ffffffffffffffff8111156114a4576114a4611d70565b6040519080825280601f01601f1916602001820160405280156114ce576020820181803683370190505b5090505b8415611058576114e360018361220b565b91506114f0600a8661229c565b6114fb90603061221e565b60f81b8183815181106115105761151061205b565b60200101906001600160f81b031916908160001a905350611532600a86612047565b94506114d2565b60006001600160e01b031982166380ac58cd60e01b148061156a57506001600160e01b03198216635b5e139f60e01b145b8061055657506301ffc9a760e01b6001600160e01b0319831614610556565b600081815260136020526040902042905561077c838383611862565b6001600160a01b038316156116df576000818152601160209081526040808320546001600160a01b03871684526010909252822080549192916115ea9060019061220b565b815481106115fa576115fa61205b565b60009182526020808320909101546001600160a01b0388168352601090915260409091208054919250906116309060019061220b565b815481106116405761164061205b565b906000526020600020015460106000876001600160a01b03166001600160a01b0316815260200190815260200160002083815481106116815761168161205b565b60009182526020808320909101929092556001600160a01b03871681526010909152604090208054806116b6576116b66122b0565b600082815260208082208301600019908101839055909201909255918152601190915260409020555b6001600160a01b0382161561077c576001600160a01b03919091166000908152601060208181526040808420805486865260118452918520829055928252600181018355918352909120015550565b611738838361191a565b6117456000848484611761565b61077c5760405162461bcd60e51b81526004016106db90612231565b60006001600160a01b0384163b1561185757604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906117a59033908990889088906004016122c6565b6020604051808303816000875af19250505080156117e0575060408051601f3d908101601f191682019092526117dd91810190612303565b60015b61183d573d80801561180e576040519150601f19603f3d011682016040523d82523d6000602084013e611813565b606091505b5080516000036118355760405162461bcd60e51b81526004016106db90612231565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611058565b506001949350505050565b6001600160a01b0383166118bd576118b881600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6118e0565b816001600160a01b0316836001600160a01b0316146118e0576118e08382611a70565b6001600160a01b0382166118f75761077c81611b0d565b826001600160a01b0316826001600160a01b03161461077c5761077c8282611bbc565b6001600160a01b0382166119705760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016106db565b6000818152600260205260409020546001600160a01b0316156119d55760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016106db565b6119e160008383611589565b6001600160a01b0382166000908152600360205260408120805460019290611a0a90849061221e565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4610c90600083836115a5565b60006001611a7d84610bcc565b611a87919061220b565b600083815260076020526040902054909150808214611ada576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611b1f9060019061220b565b60008381526009602052604081205460088054939450909284908110611b4757611b4761205b565b906000526020600020015490508060088381548110611b6857611b6861205b565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611ba057611ba06122b0565b6001900381819060005260206000200160009055905550505050565b6000611bc783610bcc565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160e01b031981168114610e2657600080fd5b600060208284031215611c2857600080fd5b8135611c3381611c00565b9392505050565b80356001600160a01b0381168114610bc757600080fd5b600060208284031215611c6357600080fd5b611c3382611c3a565b60005b83811015611c87578181015183820152602001611c6f565b50506000910152565b60008151808452611ca8816020860160208601611c6c565b601f01601f19169290920160200192915050565b602081526000611c336020830184611c90565b600060208284031215611ce157600080fd5b5035919050565b60008060408385031215611cfb57600080fd5b611d0483611c3a565b946020939093013593505050565b600080600060608486031215611d2757600080fd5b611d3084611c3a565b9250611d3e60208501611c3a565b9150604084013590509250925092565b60008060408385031215611d6157600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff80841115611da157611da1611d70565b604051601f8501601f19908116603f01168101908282118183101715611dc957611dc9611d70565b81604052809350858152868686011115611de257600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215611e0e57600080fd5b813567ffffffffffffffff811115611e2557600080fd5b8201601f81018413611e3657600080fd5b61105884823560208401611d86565b60008060408385031215611e5857600080fd5b611e6183611c3a565b915060208301358015158114611e7657600080fd5b809150509250929050565b60008060008060808587031215611e9757600080fd5b611ea085611c3a565b9350611eae60208601611c3a565b925060408501359150606085013567ffffffffffffffff811115611ed157600080fd5b8501601f81018713611ee257600080fd5b611ef187823560208401611d86565b91505092959194509250565b60008060408385031215611f1057600080fd5b611f1983611c3a565b9150611f2760208401611c3a565b90509250929050565b6020808252825182820181905260009190848201906040850190845b81811015611f6857835183529284019291840191600101611f4c565b50909695505050505050565b600181811c90821680611f8857607f821691505b602082108103611fa857634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561202c5761202c611ffc565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261205657612056612031565b500490565b634e487b7160e01b600052603260045260246000fd5b601f82111561077c57600081815260208120601f850160051c810160208610156120985750805b601f850160051c820191505b818110156120b7578281556001016120a4565b505050505050565b815167ffffffffffffffff8111156120d9576120d9611d70565b6120ed816120e78454611f74565b84612071565b602080601f831160018114612122576000841561210a5750858301515b600019600386901b1c1916600185901b1785556120b7565b600085815260208120601f198616915b8281101561215157888601518255948401946001909101908401612132565b508582101561216f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008251612191818460208701611c6c565b9190910192915050565b600083516121ad818460208801611c6c565b8351908301906121c1818360208801611c6c565b64173539b7b760d91b9101908152600501949350505050565b600082516121ec818460208701611c6c565b6c31b7b73a3930b1ba173539b7b760991b920191825250600d01919050565b8181038181111561055657610556611ffc565b8082018082111561055657610556611ffc565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60006001820161229557612295611ffc565b5060010190565b6000826122ab576122ab612031565b500690565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906122f990830184611c90565b9695505050505050565b60006020828403121561231557600080fd5b8151611c3381611c0056fea164736f6c6343000810000a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002e68747470733a2f2f6170692e7969656c64696669636174696f6e2e636f6d2f70667964662f6d657461646174612f000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104285760003560e01c80638f0525ec1161022b578063d19529ff11610130578063e34274ef116100b8578063f53d9ec111610087578063f53d9ec114610aeb578063f5ae090c14610afe578063f707159714610b07578063fd5891c414610b1a578063fffa41b114610b2d57600080fd5b8063e34274ef14610a9f578063e867d90414610ab2578063ee9b802714610ac5578063f2fde38b14610ad857600080fd5b8063dc731318116100ff578063dc73131814610a48578063df72ad2714610a5b578063e03527d514610a70578063e0a3614314610a83578063e282f76014610a9657600080fd5b8063d19529ff146109f1578063d2c76d74146109fa578063d5e3483614610a0d578063d834123e14610a3557600080fd5b8063adfa3199116101b3578063b91d08ce11610182578063b91d08ce14610996578063ba93fd90146109a9578063c70a900f146109b2578063cb038907146109d5578063d14d40bb146109e857600080fd5b8063adfa319914610946578063ae3302c214610959578063b54710e71461097a578063b81bb7101461098d57600080fd5b806399fbab88116101fa57806399fbab881461081f578063a126d601146108f8578063a1db97821461090b578063a2f0a1f21461091e578063a52e53691461093357600080fd5b80638f0525ec146107a957806391bb214b146107bc57806392f8eb94146107d157806396e61bc7146107f657600080fd5b806356c308ca116103315780636b4b6866116102b95780637c011be8116102885780637c011be8146107445780637f3b7a0214610757578063861d1dfa1461076057806389701db5146107855780638da5cb5b1461079857600080fd5b80636b4b6866146106f55780636e04ff0d14610708578063715018a61461072957806377a354651461073157600080fd5b80635ba87310116103005780635ba873101461067c5780635bc412d91461068f57806362c7536d146106a257806365f290f7146106c257806366c62643146106e257600080fd5b806356c308ca14610608578063589201401461061b578063594a60ae146106565780635ad15eda1461066957600080fd5b8063328d8f72116103b45780633db52911116103835780633db52911146105ae5780634585e33b146105c157806348bb4e33146105d45780634dfdeee5146105e75780634f8f5332146105f057600080fd5b8063328d8f721461053f578063335db3061461055257806339d99cca146105725780633a2baafd1461058557600080fd5b8063174b6399116103fb578063174b639914610496578063182d8747146104b65780631a090154146104d95780631a79344c146104ec578063238dafe01461052b57600080fd5b80630679d3621461042d5780630f1627931461044257806310edc9801461046857806313114a9d1461048d575b600080fd5b61044061043b3660046151d6565b610b40565b005b6104556104503660046151fa565b610ba6565b6040519081526020015b60405180910390f35b6002546001600160a01b03165b6040516001600160a01b03909116815260200161045f565b61045560115481565b6104556104a4366004615228565b60166020526000908152604090205481565b6104c96104c43660046151fa565b610dc9565b604051901515815260200161045f565b6104406104e73660046151fa565b610ef0565b6104ff6104fa3660046151fa565b611043565b60408051958652602086019490945292840191909152151560608301521515608082015260a00161045f565b6004546104c990600160a01b900460ff1681565b61044061054d366004615253565b611364565b6105656105603660046151fa565b61138a565b60405161045f9190615270565b6104406105803660046152ce565b611410565b6104756105933660046151fa565b6018602052600090815260409020546001600160a01b031681565b6104c96105bc3660046152eb565b611469565b6104406105cf36600461530d565b611771565b6104406105e23660046152ce565b61188d565b610455600c5481565b6006546104759061010090046001600160a01b031681565b6104406106163660046151fa565b6118b3565b61062e610629366004615228565b6118fc565b6040805161ffff90941684526001600160501b0390921660208401529082015260600161045f565b61044061066436600461537f565b611a7a565b6104c96106773660046151fa565b611b22565b61045561068a3660046151fa565b611db2565b61044061069d3660046151fa565b611dd3565b6104556106b0366004615228565b60156020526000908152604090205481565b6104556106d0366004615228565b60146020526000908152604090205481565b6104406106f03660046151fa565b611e31565b6104406107033660046152eb565b611e8f565b61071b61071636600461530d565b611f36565b60405161045f9291906153f1565b610440611fab565b61044061073f366004615414565b611fbf565b6104406107523660046152eb565b61204b565b610455600e5481565b600a546107739062010000900460ff1681565b60405160ff909116815260200161045f565b6104406107933660046151fa565b6120f2565b6001546001600160a01b0316610475565b6104556107b73660046151fa565b612178565b6107c46121b1565b60405161045f919061544d565b6107e46107df3660046151fa565b612213565b60405161045f9695949392919061549a565b6104756108043660046151fa565b6019602052600090815260409020546001600160a01b031681565b6108e061082d3660046151fa565b601760209081526000918252604091829020825160c081018452600182015481526002820154928101929092526003810154928201929092526004820154606082015260058201546080820152600682015460a0820152600782015460088301546009840154600a850154600b860154600c870154600d880154600e890154600f8a01546010909a015498996001600160a01b039098169896979596949560ff8086169661010090960461ffff1695168c565b60405161045f9c9b9a999897969594939291906154d6565b6104406109063660046151fa565b6122e7565b610440610919366004615594565b6122f5565b610926612413565b60405161045f91906155c0565b6104406109413660046156c3565b6125be565b6104406109543660046151fa565b612db8565b600a546109679061ffff1681565b60405161ffff909116815260200161045f565b6107c46109883660046151fa565b612e17565b610455600f5481565b6104556109a43660046151fa565b612faf565b610455600d5481565b6104c96109c0366004615228565b60056020526000908152604090205460ff1681565b6104406109e33660046151fa565b612fbf565b61045560105481565b610455600b5481565b610440610a08366004615594565b61300c565b610a20610a1b3660046151fa565b613030565b6040805192835260208301919091520161045f565b610440610a43366004615228565b6131a7565b610a20610a563660046152eb565b6131d1565b610a6361320d565b60405161045f919061572a565b610440610a7e36600461537f565b613264565b610440610a913660046151fa565b613615565b61045560135481565b610455610aad3660046151fa565b613674565b610440610ac0366004615228565b6139a7565b610440610ad3366004615414565b613a12565b610440610ae6366004615228565b613bd5565b610440610af93660046151fa565b613c4b565b61045560125481565b610455610b15366004615841565b613d6c565b610440610b28366004615960565b613e19565b610440610b3b366004615a3c565b614076565b610b486140c1565b6109c48161ffff161115610b8e5760405162461bcd60e51b81526020600482015260086024820152670dac2f040646a60f60c31b60448201526064015b60405180910390fd5b600a805461ffff191661ffff92909216919091179055565b60008060008381548110610bbc57610bbc615a77565b90600052602060002090600702016040518060e0016040529081600082018054610be590615a8d565b80601f0160208091040260200160405190810160405280929190818152602001828054610c1190615a8d565b8015610c5e5780601f10610c3357610100808354040283529160200191610c5e565b820191906000526020600020905b815481529060010190602001808311610c4157829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201805480602002602001604051908101604052809291908181526020016000905b82821015610d19576000848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b900461ffff1683850152600190810154918301919091529083529092019101610cbe565b50505091525090915060009050805b8260c0015151811015610dc15760008360c001518281518110610d4d57610d4d615a77565b602002602001015190506000610d6682600001516118fc565b925050508160400151600014610d9e57670de0b6b3a7640000826040015182610d8f9190615add565b610d999190615afc565b610da0565b805b610daa9085615b1e565b935050508080610db990615b31565b915050610d28565b509392505050565b6000818152601a6020908152604080832080548251818502810185019093528083528493849084015b82821015610e3857838290600052602060002090600202016040518060400160405290816000820154815260200160018201548152505081526020019060010190610df2565b5050505090506000610e4984613674565b905060005b8251811015610ee5576000838281518110610e6b57610e6b615a77565b60200260200101516020015190506000848381518110610e8d57610e8d615a77565b602002602001015160000151821090508015610ebc57818411610eb7575060019695505050505050565b610ed0565b818410610ed0575060019695505050505050565b50508080610edd90615b31565b915050610e4e565b506000949350505050565b610ef86140c1565b6000808281548110610f0c57610f0c615a77565b906000526020600020906007020190506001816006018054905011610f5b5760405162461bcd60e51b8152602060048201526005602482015264092a69288b60db1b6044820152606401610b85565b60005b600682015481101561103e576000610fa3836006018381548110610f8457610f84615a77565b60009182526020909120600290910201546001600160a01b03166118fc565b92505050806002670de0b6b3a7640000610fbd9190615c26565b846006018481548110610fd257610fd2615a77565b6000918252602090912060029091020154610ff89190600160a01b900461ffff16615add565b6110029190615afc565b83600601838154811061101757611017615a77565b6000918252602090912060016002909202010155508061103681615b31565b915050610f5e565b505050565b60008060008060008060176000888152602001908152602001600020604051806101a001604052908160008201805480602002602001604051908101604052809291908181526020016000905b8282101561113757600084815260209081902060408051610100810182526003860290920180546001600160a01b03811660a0850190815261ffff600160a01b909204821660c086015260018084015460e0870152908552600290920154808216858701526001600160501b03620100008204811694860194909452600160601b81049091166060850152600160701b900490911660808301529083529092019101611090565b505050908252506040805160c080820183526001858101548352600286015460208481019190915260038701548486015260048701546060808601919091526005880154608080870191909152600689015460a0808801919091529288019590955260078801546001600160a01b031695870195909552600887015494860194909452600986015492850192909252600a85015492840192909252600b84015460ff80821615159385019390935261ffff610100918290041660e0850152600c85015490840152600d840154610120840152600e840154610140840152600f84015461016084015260109093015416151561018090910152909150600061123d89613674565b61010084015190915080821190821060008261126957838661010001516112649190615c35565b611279565b6101008601516112799085615c35565b90506000866101000151828860a001516112939190615add565b61129d9190615afc565b905060008760c001516112b057836112b2565b845b60808901519091508115611330576000620186a0600c548b61010001516112d99190615add565b6112e39190615afc565b85101590506000600b548b60200151600001516113009190615b1e565b4210159050818061130e5750805b156113245761131d8584615b1e565b9250611329565b600099505b505061134d565b808311156113405750600061134d565b61134a8382615c35565b90505b959e959d50909b5099509397509195505050505050565b61136c6140c1565b60048054911515600160a01b0260ff60a01b19909216919091179055565b6060601a6000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611405578382906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906113bf565b505050509050919050565b6114186140c1565b60008160ff16116114535760405162461bcd60e51b81526020600482015260056024820152646d696e203160d81b6044820152606401610b85565b6006805460ff191660ff92909216919091179055565b600081156114775781611479565b425b9150600080848154811061148f5761148f615a77565b90600052602060002090600702016040518060e00160405290816000820180546114b890615a8d565b80601f01602080910402602001604051908101604052809291908181526020018280546114e490615a8d565b80156115315780601f1061150657610100808354040283529160200191611531565b820191906000526020600020905b81548152906001019060200180831161151457829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201805480602002602001604051908101604052809291908181526020016000905b828210156115ec576000848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b900461ffff1683850152600190810154918301919091529083529092019101611591565b50505050815250509050600181604001511015801561161057506001816060015110155b156116ae576004805460405163045f145760e31b81529182018590526000916001600160a01b03909116906322f8a2b890602401602060405180830381865afa158015611661573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116859190615c48565b9050816040015181108061169c5750816060015181115b156116ac5760009250505061176b565b505b600181608001511015806116c7575060018160a0015110155b156117655760048054604051631f11cf0d60e11b81529182018590526000916001600160a01b0390911690633e239e1a90602401602060405180830381865afa158015611718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173c9190615c48565b9050816080015181108061175357508160a0015181115b156117635760009250505061176b565b505b60019150505b92915050565b6000805b601b54811015611887576000601b828154811061179457611794615a77565b9060005260206000200154905060006117ac82611b22565b905060006117b983610dc9565b905081806117c45750805b15611871576117d483600161411b565b846117de81615c61565b955050811561181f576040518381527feb7f91469bb290996747407607c0d2bf6b0d11afb8d5ada15dd2269709879eaf9060200160405180910390a1611859565b8015611859576040518381527fb2f224dd9601ae969b3a64ea0493482e0eead1fa818bc855679c3ad666ea1fef9060200160405180910390a15b60065460ff9081169086161061187157505050611887565b505050808061187f90615b31565b915050611775565b50505050565b6118956140c1565b600a805460ff909216620100000262ff000019909216919091179055565b6118bb6140c1565b6102588110156118f75760405162461bcd60e51b81526020600482015260076024820152666d696e2031306d60c81b6044820152606401610b85565b600f55565b6000806000808490506000816001600160a01b03166358303b106040518163ffffffff1660e01b8152600401602060405180830381865afa158015611945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119699190615c80565b90506000826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119cf9190615c9d565b9050600080846001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015611a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a369190615cd6565b50505091509150838284600a611a4c9190615c26565b611a5e90670de0b6b3a7640000615afc565b611a689084615add565b97509750975050505050509193909250565b6002546040516331a9108f60e11b81526004810185905284916001600160a01b031690636352211e90602401602060405180830381865afa158015611ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ae79190615d26565b6001600160a01b0316336001600160a01b031614611b175760405162461bcd60e51b8152600401610b8590615d43565b6118878484846143a0565b6000818152601760209081526040808320815181546101c0948102820185019093526101a08101838152859491938492849190879085015b82821015611c0157600084815260209081902060408051610100810182526003860290920180546001600160a01b03811660a0850190815261ffff600160a01b909204821660c086015260018084015460e0870152908552600290920154808216858701526001600160501b03620100008204811694860194909452600160601b81049091166060850152600160701b900490911660808301529083529092019101611b5a565b505050908252506040805160c0808201835260018501548252600285015460208381019190915260038601548385015260048601546060808501919091526005870154608080860191909152600688015460a0808701919091529287019490945260078701546001600160a01b031694860194909452600886015493850193909352600985015491840191909152600a84015491830191909152600b83015460ff80821615159284019290925261ffff610100918290041660e0840152600c84015490830152600d830154610120830152600e830154610140830152600f83015461016083015260109092015490911615156101809091015290506000611d0784612178565b9050600080611d1586613030565b915091506000806000611d2789611043565b509350509250925060008760c00151611d505786886101000151611d4b9190615b1e565b611d61565b86886101000151611d619190615c35565b905060008860c00151611d775781851015611d7c565b818511155b9050600083158015611d97575084611d94888a615b1e565b10155b90508180611da25750805b9c9b505050505050505050505050565b601d8181548110611dc257600080fd5b600091825260209091200154905081565b611ddb6140c1565b6064611deb620186a06001615add565b611df59190615afc565b8110611e2c5760405162461bcd60e51b81526020600482015260066024820152656d617820312560d01b6044820152606401610b85565b601055565b611e396140c1565b6064611e49620186a06003615add565b611e539190615afc565b8110611e8a5760405162461bcd60e51b81526020600482015260066024820152656d617820332560d01b6044820152606401610b85565b600c55565b6002546040516331a9108f60e11b81526004810184905283916001600160a01b031690636352211e90602401602060405180830381865afa158015611ed8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611efc9190615d26565b6001600160a01b0316336001600160a01b031614611f2c5760405162461bcd60e51b8152600401610b8590615d43565b61103e8383614463565b6000606060005b601b54811015611fa3576000601b8281548110611f5c57611f5c615a77565b90600052602060002001549050611f7281611b22565b80611f815750611f8181610dc9565b15611f90576001935050611fa3565b5080611f9b81615b31565b915050611f3d565b509250929050565b611fb36140c1565b611fbd6000614521565b565b611fc76140c1565b6001600160a01b03821660009081526005602052604090205481151560ff9091161515036120205760405162461bcd60e51b8152600401610b85906020808252600490820152635345543360e01b604082015260600190565b6001600160a01b03919091166000908152600560205260409020805460ff1916911515919091179055565b6002546040516331a9108f60e11b81526004810184905283916001600160a01b031690636352211e90602401602060405180830381865afa158015612094573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b89190615d26565b6001600160a01b0316336001600160a01b0316146120e85760405162461bcd60e51b8152600401610b8590615d43565b61103e8383614573565b6120fa6140c1565b60065460405163a9059cbb60e01b81526101009091046001600160a01b031660048201819052602482018390529063a9059cbb906044016020604051808303816000875af1158015612150573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121749190615d6e565b5050565b6000818152601760205260408120600b810154600c9091015461010090910461ffff16906121a7906009615add565b61176b9190615afc565b6060600880548060200260200160405190810160405280929190818152602001828054801561220957602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121eb575b5050505050905090565b6000818154811061222357600080fd5b906000526020600020906007020160009150905080600001805461224690615a8d565b80601f016020809104026020016040519081016040528092919081815260200182805461227290615a8d565b80156122bf5780601f10612294576101008083540402835291602001916122bf565b820191906000526020600020905b8154815290600101906020018083116122a257829003601f168201915b5050505050908060010154908060020154908060030154908060040154908060050154905086565b6122f281600061411b565b50565b6122fd6140c1565b81811561230a5781612372565b6040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa15801561234e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123729190615c48565b91506000821161238157600080fd5b806001600160a01b031663a9059cbb6123a26001546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303816000875af11580156123ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118879190615d6e565b60606000805480602002602001604051908101604052809291908181526020016000905b828210156125b557838290600052602060002090600702016040518060e001604052908160008201805461246a90615a8d565b80601f016020809104026020016040519081016040528092919081815260200182805461249690615a8d565b80156124e35780601f106124b8576101008083540402835291602001916124e3565b820191906000526020600020905b8154815290600101906020018083116124c657829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201805480602002602001604051908101604052809291908181526020016000905b8282101561259e576000848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b900461ffff1683850152600190810154918301919091529083529092019101612543565b505050508152505081526020019060010190612437565b50505050905090565b600454600160a01b900460ff166126025760405162461bcd60e51b8152602060048201526008602482015267111254d05093115160c21b6044820152606401610b85565b600054851061263c5760405162461bcd60e51b81526020600482015260066024820152650929cac9288b60d31b6044820152606401610b85565b600a8361ffff161015801561265b5750600a5461ffff90811690841611155b6126905760405162461bcd60e51b8152600401610b85906020808252600490820152634c45563160e01b604082015260600190565b61269b856000611469565b6126d15760405162461bcd60e51b8152602060048201526007602482015266494e444f4f423160c81b6044820152606401610b85565b6001600160a01b03861615806126f957506006546001600160a01b0387811661010090920416145b8061271c57506001600160a01b03861660009081526007602052604090205460ff165b6127545760405162461bcd60e51b8152602060048201526009602482015268504f53544f4b454e3160b81b6044820152606401610b85565b60006001600160a01b0387161561276b578661277d565b60065461010090046001600160a01b03165b6040516370a0823160e01b815233600482015290915085906001600160a01b038316906370a0823190602401602060405180830381865afa1580156127c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ea9190615c48565b10156128215760405162461bcd60e51b8152600401610b859060208082526004908201526342414c3160e01b604082015260600190565b6002546040516335313c2160e11b81523360048201526000916001600160a01b031690636a627842906024016020604051808303816000875af115801561286c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128909190615c48565b6040516323b872dd60e01b8152336004820152306024820152604481018890529091506001600160a01b038316906323b872dd906064016020604051808303816000875af11580156128e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061290a9190615d6e565b50600061291b878761ffff16614680565b905060006129298289615c35565b9050816011600082825461293d9190615b1e565b925050819055506000808a8154811061295857612958615a77565b90600052602060002090600702016040518060e001604052908160008201805461298190615a8d565b80601f01602080910402602001604051908101604052809291908181526020018280546129ad90615a8d565b80156129fa5780601f106129cf576101008083540402835291602001916129fa565b820191906000526020600020905b8154815290600101906020018083116129dd57829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201805480602002602001604051908101604052809291908181526020016000905b82821015612ab5576000848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b900461ffff1683850152600190810154918301919091529083529092019101612a5a565b5050509152505060008581526017602052604081209192505b8260c0015151811015612c585760008360c001518281518110612af357612af3615a77565b60200260200101519050600080612b0d83600001516118fc565b5091509150846000016040518060a001604052808860c001518781518110612b3757612b37615a77565b602090810291909101810151825261ffff958616828201526001600160501b03948516604080840191909152600060608085018290526080948501829052865460018181018955978352918490208651805160039094029091018054828701518c16600160a01b026001600160b01b03199091166001600160a01b0390951694909417939093178355830151968201969096559184015160029092018054918501519585015194909301518616600160701b0269ffffffffffffffffffff60701b19948816600160601b02949094166bffffffffffffffffffffffff60601b199590961662010000026bffffffffffffffffffffffff1990911691909616179490941791909116919091171790555080612c5081615b31565b915050612ace565b506000612c648c610ba6565b600087815260186020526040902080546001600160a01b0319163317905542600184015560028301869055600983018590559050600a612ca861ffff8c1686615add565b612cb29190615afc565b600a830155600b8201805462ffffff19168a151562ffff0019161761010061ffff8d1602179055600c82018190556007820180546001600160a01b0319166001600160a01b038916179055601b80546000888152601c60205260408120829055600182018355919091527f3ad8aa4f87544323a9d1e5dd902f40c356527a7955687113db5f9a85ad579dc101869055612d4a866146ff565b8715612d5a57612d5a8689614573565b60408051828152602081018690528a15158183015261ffff8c1660608201529051339188917f7851a428332e40237ac34a5efd508d9bbff0fb057da46bf99e1bd1b5c4adf6719181900360800190a350505050505050505050505050565b612dc06140c1565b6064612dd0620186a0600a615add565b612dda9190615afc565b8110612e125760405162461bcd60e51b81526020600482015260076024820152666d61782031302560c81b6044820152606401610b85565b600e55565b6000818152601760209081526040808320805482518185028101850190935280835260609493849084015b82821015612ee957600084815260209081902060408051610100810182526003860290920180546001600160a01b03811660a0850190815261ffff600160a01b909204821660c086015260018084015460e0870152908552600290920154808216858701526001600160501b03620100008204811694860194909452600160601b81049091166060850152600160701b900490911660808301529083529092019101612e42565b50505060008581526017602052604081205492935091905067ffffffffffffffff811115612f1957612f19615762565b604051908082528060200260200182016040528015612f42578160200160208202803683370190505b50905060005b8251811015610dc157828181518110612f6357612f63615a77565b60200260200101516000015160000151828281518110612f8557612f85615a77565b6001600160a01b039092166020928302919091019091015280612fa781615b31565b915050612f48565b601b8181548110611dc257600080fd5b612fc76140c1565b620151808111156130075760405162461bcd60e51b815260206004820152600a6024820152696d61782031206461797360b01b6044820152606401610b85565b600b55565b6130146140c1565b6001600160a01b03909116600090815260166020526040902055565b6002546040516331a9108f60e11b815260048101839052600091829182916001600160a01b031690636352211e90602401602060405180830381865afa15801561307e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a29190615d26565b90506000806130b083614a91565b600e546000898152601760205260408120600a01549395509193509091620186a0916130db91615add565b6130e59190615afc565b6010546000898152601760205260408120600a015492935091620186a09161310c91615add565b6131169190615afc565b600f5460008a815260176020526040812060010154929350916131399042615c35565b6131439084615add565b61314d9190615afc565b9050841561319857836131608685615add565b61316a9190615afc565b6131749084615c35565b9250836131818683615add565b61318b9190615afc565b6131959082615c35565b90505b91989197509095505050505050565b6131af6140c1565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b601a60205281600052604060002081815481106131ed57600080fd5b600091825260209091206002909102018054600190910154909250905082565b6060601d80548060200260200160405190810160405280929190818152602001828054801561220957602002820191906000526020600020905b815481526020019060010190808311613247575050505050905090565b3360009081526005602052604090205460ff166132b35760405162461bcd60e51b815260206004820152600d60248201526c6f6e6c7920736574746c65727360981b6044820152606401610b85565b6000838152601760205260409020601081015460ff16156132ff5760405162461bcd60e51b8152600401610b85906020808252600490820152635345543160e01b604082015260600190565b600081600801541161333c5760405162461bcd60e51b8152600401610b859060208082526004908201526329a2aa1960e11b604082015260600190565b60108101805460ff19166001179055600581018390556006810182905560078101546040805163313ce56760e01b815290516000926001600160a01b03169163313ce5679160048281019260209291908290030181865afa1580156133a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133c99190615c9d565b6133d490600a615c26565b8385600660019054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015613429573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061344d9190615c9d565b61345890600a615c26565b85600801546134679190615add565b6134719190615add565b61347b9190615afc565b6134859190615afc565b6006546000878152601960205260409081902054905163a9059cbb60e01b81526001600160a01b03918216600482015260248101849052929350610100909104169063a9059cbb906044016020604051808303816000875af11580156134ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135139190615d6e565b506000858152601e6020526040812054601d805491929161353690600190615c35565b8154811061354657613546615a77565b6000918252602080832090910154898352601e9091526040808320839055818352909120839055601d805491925082918490811061358657613586615a77565b600091825260209091200155601d8054806135a3576135a3615d8b565b600190038181906000526020600020016000905590557f4c246f6c8d41233463bbb11c80907ea3f18c0b7c101910bfa5a599f65cacab4f87848888604051613604949392919093845260208401929092526040830152606082015260800190565b60405180910390a150505050505050565b61361d6140c1565b606461362d620186a0600a615add565b6136379190615afc565b811061366f5760405162461bcd60e51b81526020600482015260076024820152666d61782031302560c81b6044820152606401610b85565b600d55565b6000818152601760209081526040808320815181546101c0948102820185019093526101a08101838152859491938492849190879085015b8282101561375357600084815260209081902060408051610100810182526003860290920180546001600160a01b03811660a0850190815261ffff600160a01b909204821660c086015260018084015460e0870152908552600290920154808216858701526001600160501b03620100008204811694860194909452600160601b81049091166060850152600160701b9004909116608083015290835290920191016136ac565b505050908252506040805160c0808201835260018501548252600285015460208381019190915260038601548385015260048601546060808501919091526005870154608080860191909152600688015460a0808701919091529287019490945260078701546001600160a01b031694860194909452600886015493850193909352600985015491840191909152600a84015491830191909152600b83015460ff80821615159284019290925261ffff610100918290041660e0840152600c84015490830152600d830154610120830152600e830154610140830152600f83015461016083015260109092015490911615156101809091015280515190915060009067ffffffffffffffff81111561386d5761386d615762565b604051908082528060200260200182016040528015613896578160200160208202803683370190505b509050600082600001515167ffffffffffffffff8111156138b9576138b9615762565b6040519080825280602002602001820160405280156138e2578160200160208202803683370190505b50905060005b83515181101561399357835180518290811061390657613906615a77565b6020026020010151600001516000015183828151811061392857613928615a77565b6001600160a01b0390921660209283029190910190910152835180518290811061395457613954615a77565b6020026020010151600001516040015182828151811061397657613976615a77565b60209081029190910101528061398b81615b31565b9150506138e8565b5061399e8282613d6c565b95945050505050565b6139af6140c1565b601b54156139ea5760405162461bcd60e51b81526020600482015260086024820152671350525390d3d31360c21b6044820152606401610b85565b600680546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b613a1a6140c1565b6001600160a01b03821660009081526007602052604090205481151560ff909116151503613a795760405162461bcd60e51b815260206004820152600c60248201526b6368616e676520737461746560a01b6044820152606401610b85565b6001600160a01b0382166000908152600760205260409020805460ff19168215801591909117909155613b0657600880546001600160a01b0384166000818152600960205260408120839055600183018455929092527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b03191690911790555050565b6001600160a01b0382166000908152600960205260408120805491905560088054613b3390600190615c35565b81548110613b4357613b43615a77565b600091825260209091200154600880546001600160a01b039092169183908110613b6f57613b6f615a77565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506008805480613bae57613bae615d8b565b600082815260209020810160001990810180546001600160a01b0319169055019055505050565b613bdd6140c1565b6001600160a01b038116613c425760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b85565b6122f281614521565b613c536140c1565b60008054613c6390600190615c35565b81548110613c7357613c73615a77565b906000526020600020906007020160008281548110613c9457613c94615a77565b6000918252602090912060079091020180613caf8382615def565b5060018201548160010155600282015481600201556003820154816003015560048201548160040155600582015481600501556006820181600601908054613cf8929190615098565b509050506000805480613d0d57613d0d615d8b565b60008281526020812060001990920191600783020190613d2d8282615134565b60018201600090556002820160009055600382016000905560048201600090556005820160009055600682016000613d65919061516e565b5050905550565b60008151835114613d7c57600080fd5b6000805b8451811015610dc1576000613dad868381518110613da057613da0615a77565b60200260200101516118fc565b925050508551600114613df757670de0b6b3a7640000858381518110613dd557613dd5615a77565b602002602001015182613de89190615add565b613df29190615afc565b613df9565b805b613e039084615b1e565b9250508080613e1190615b31565b915050613d80565b613e216140c1565b60008251118015613e33575080518251145b613e6a5760405162461bcd60e51b815260206004820152600860248201526739b0b6b2903632b760c11b6044820152606401610b85565b600080546001810182559080526007027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5630180613ea78582615ecc565b5060005b835181101561406f576000848281518110613ec857613ec8615a77565b602002602001015190506000613edd826118fc565b9250505060008111613f215760405162461bcd60e51b815260206004820152600d60248201526c696e76616c69642070726f787960981b6044820152606401610b85565b8551600114613f4957848381518110613f3c57613f3c615a77565b6020026020010151613f4c565b60005b61ffff16846001016000828254613f639190615b1e565b92505081905550836006016040518060600160405280846001600160a01b03168152602001878681518110613f9a57613f9a615a77565b602002602001015161ffff1681526020018851600114613fff5783613fc86002670de0b6b3a7640000615c26565b898881518110613fda57613fda615a77565b602002602001015161ffff16613ff09190615add565b613ffa9190615afc565b614002565b60005b90528154600181810184556000938452602093849020835160029093020180549484015161ffff16600160a01b026001600160b01b03199095166001600160a01b03909316929092179390931781556040909101519101555081905061406781615b31565b915050613eab565b5050505050565b61407e6140c1565b600080868154811061409257614092615a77565b600091825260209091206007909102016002810195909555506003840192909255600483015560059091015550565b6001546001600160a01b03163314611fbd5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b85565b60008281526017602052604080822060025491516331a9108f60e11b8152600481018690529092916001600160a01b031690636352211e90602401602060405180830381865afa158015614173573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141979190615d26565b905082806141ad5750336001600160a01b038216145b6141e15760405162461bcd60e51b81526020600482015260056024820152644f574e4c5160d81b6044820152606401610b85565b60025460405163c3738f3f60e01b8152600481018690526001600160a01b039091169063c3738f3f90602401602060405180830381865afa15801561422a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061424e9190615d6e565b6142835760405162461bcd60e51b8152602060048201526006602482015265434c4f53453160d01b6044820152606401610b85565b61428d8482614b24565b61429684614c50565b61429f84614cfa565b6142a884614dbb565b600254604051630852cd8d60e31b8152600481018690526001600160a01b03909116906342966c6890602401600060405180830381600087803b1580156142ee57600080fd5b505af1158015614302573d6000803e3d6000fd5b5050506000858152601960205260409081902080546001600160a01b0385166001600160a01b03199091168117909155600c850154600d860154600e870154600f880154945193955089947fad61fdefcf969920b58ee3fc753c769d85f23f36b446cf737c0c5e7dcf840a6e94614392949392919093845260208401929092526040830152606082015260800190565b60405180910390a350505050565b600081116143d65760405162461bcd60e51b81526020600482015260036024820152620544f360ec1b6044820152606401610b85565b6000838152601a602052604081208054849081106143f6576143f6615a77565b90600052602060002090600202019050600081600001548260010154109050806144235781548311614428565b815483105b61445a5760405162461bcd60e51b8152602060048201526003602482015262544f3360e81b6044820152606401610b85565b50600101555050565b6000828152601a60205260409020805461447f90600190615c35565b8154811061448f5761448f615a77565b9060005260206000209060020201601a600084815260200190815260200160002082815481106144c1576144c1615a77565b6000918252602080832084546002909302019182556001938401549390910192909255838152601a909152604090208054806144ff576144ff615d8b565b6000828152602081206002600019909301928302018181556001015590555050565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600081116145a95760405162461bcd60e51b81526020600482015260036024820152620544f360ec1b6044820152606401610b85565b600a546000838152601a60205260409020546201000090910460ff16116145f85760405162461bcd60e51b8152602060048201526003602482015262544f3160e81b6044820152606401610b85565b600061460383613674565b905081810361463a5760405162461bcd60e51b81526020600482015260036024820152622a279960e91b6044820152606401610b85565b6000928352601a60209081526040808520815180830190925292815280820193845282546001818101855593865291909420935160029091029093019283559051910155565b600080600a61468f8486615add565b6146999190615afc565b90506000620186a0600d54836146af9190615add565b6146b99190615afc565b90506000806146c733614a91565b909250905081156146f457806146dd8385615add565b6146e79190615afc565b6146f19084615c35565b92505b509095945050505050565b6000818152601760209081526040808320815181546101c0948102820185019093526101a08101838152909391928492849190879085015b828210156147de57600084815260209081902060408051610100810182526003860290920180546001600160a01b03811660a0850190815261ffff600160a01b909204821660c086015260018084015460e0870152908552600290920154808216858701526001600160501b03620100008204811694860194909452600160601b81049091166060850152600160701b900490911660808301529083529092019101614737565b505050908252506040805160c0808201835260018501548252600285015460208381019190915260038601548385015260048601546060808501919091526005870154608080860191909152600688015460a0808701919091529287019490945260078701546001600160a01b031694860194909452600886015493850193909352600985015491840191909152600a84015491830191909152600b83015460ff80821615158385015261ffff610100928390041660e0850152600c85015491840191909152600d840154610120840152600e840154610140840152600f8401546101608401526010909301549092161515610180909101528101519091501561491e5760a08101516040808301516001600160a01b0316600090815260146020529081208054909190614913908490615b1e565b909155506149559050565b60a08101516040808301516001600160a01b031660009081526015602052908120805490919061494f908490615b1e565b90915550505b6040808201516001600160a01b03166000908152601660205220541561217457604080820180516001600160a01b039081166000908152601560209081528482205493519092168152601490915291822054116149ee57604080830180516001600160a01b039081166000908152601460209081528482205493519092168152601590915291909120546149e99190615c35565b614a2b565b604080830180516001600160a01b03908116600090815260156020908152848220549351909216815260149091529190912054614a2b9190615c35565b6040808401516001600160a01b031660009081526016602052205490915081111561103e5760405162461bcd60e51b81526020600482015260166024820152751b585e0818dbdb1b185d195c985b081c995858da195960521b6044820152606401610b85565b60035460009081906001600160a01b0316614aae57600080614b1b565b60035460405163a310e73960e01b81526001600160a01b0385811660048301529091169063a310e739906024016040805180830381865afa158015614af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b1b9190615f84565b91509150915091565b60008281526017602052604081209080614b3d85613030565b90925090506000614b4e8284615b1e565b90508060116000828254614b629190615b1e565b909155506000905080808080614b778b611043565b945094509450945094508115614baa578015614ba5578260126000828254614b9f9190615b1e565b90915550505b614bc2565b8260136000828254614bbc9190615b1e565b90915550505b838611614bd857614bd38685615c35565b614bdb565b60005b9350614be88b8b86614e66565b4260038a015560048901869055600d8901859055818015614c065750805b614c11576000614c13565b825b600e8a015581614c385788600901548311614c2e5782614c3b565b8860090154614c3b565b60005b89600f01819055505050505050505050505050565b6000818152601c6020526040812054601b8054919291614c7290600190615c35565b81548110614c8257614c82615a77565b6000918252602080832090910154858352601c9091526040808320839055818352909120839055601b8054919250829184908110614cc257614cc2615a77565b600091825260209091200155601b805480614cdf57614cdf615d8b565b60019003818190600052602060002001600090559055505050565b6000818152601760205260408120905b815481101561103e576000826000018281548110614d2a57614d2a615a77565b60009182526020822060039091020180549092508190614d52906001600160a01b03166118fc565b50600290940180546001600160501b03909516600160701b0269ffffffffffffffffffff60701b1961ffff909316600160601b02929092166bffffffffffffffffffffffff60601b19909516949094171790925550819050614db381615b31565b915050614d0a565b6000818152601760205260409020600b015460ff1615614e1f576000818152601760209081526040808320600a8101546007909101546001600160a01b0316845260149092528220805491929091614e14908490615c35565b909155506122f29050565b6000818152601760209081526040808320600a8101546007909101546001600160a01b0316845260159092528220805491929091614e5e908490615c35565b909155505050565b600083815260176020526040902081156150835760065460078201546001600160a01b036101009092048216911603614f285760108101805460ff19166001179055600781015460405163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529091169063a9059cbb906044015b6020604051808303816000875af1158015614efe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614f229190615d6e565b50611887565b8060090154821115615039576007810154600982015460405163a9059cbb60e01b81526001600160a01b038681166004830152602482019290925291169063a9059cbb906044016020604051808303816000875af1158015614f8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614fb29190615d6e565b506009810154614fc29083615c35565b6008820155601d80546000868152601e60205260408082208390556001830184559281527f6d4407e7be21f808e6509aa9fa9143369579dd7d760fe20a2c09680fc146134f909101869055905185917f1cf3a4d81180ed8c843ad38f7adadb6357459df6a134d14614cf7ca32dbee42191a2611887565b60108101805460ff19166001179055600781015460405163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529091169063a9059cbb90604401614edf565b60108101805460ff1916600117905550505050565b8280548282559060005260206000209060020281019282156151245760005260206000209160020282015b8281111561512457825482546001600160a01b039091166001600160a01b031982168117845584546001600160b01b031990921617600160a01b9182900461ffff1690910217825560018084015490830155600292830192909101906150c3565b5061513092915061518b565b5090565b50805461514090615a8d565b6000825580601f10615150575050565b601f0160209004906000526020600020908101906122f291906151b1565b50805460008255600202906000526020600020908101906122f291905b5b808211156151305780546001600160b01b03191681556000600182015560020161518c565b5b8082111561513057600081556001016151b2565b61ffff811681146122f257600080fd5b6000602082840312156151e857600080fd5b81356151f3816151c6565b9392505050565b60006020828403121561520c57600080fd5b5035919050565b6001600160a01b03811681146122f257600080fd5b60006020828403121561523a57600080fd5b81356151f381615213565b80151581146122f257600080fd5b60006020828403121561526557600080fd5b81356151f381615245565b602080825282518282018190526000919060409081850190868401855b828110156152b25781518051855286015186850152928401929085019060010161528d565b5091979650505050505050565b60ff811681146122f257600080fd5b6000602082840312156152e057600080fd5b81356151f3816152bf565b600080604083850312156152fe57600080fd5b50508035926020909101359150565b6000806020838503121561532057600080fd5b823567ffffffffffffffff8082111561533857600080fd5b818501915085601f83011261534c57600080fd5b81358181111561535b57600080fd5b86602082850101111561536d57600080fd5b60209290920196919550909350505050565b60008060006060848603121561539457600080fd5b505081359360208301359350604090920135919050565b6000815180845260005b818110156153d1576020818501810151868301820152016153b5565b506000602082860101526020601f19601f83011685010191505092915050565b821515815260406020820152600061540c60408301846153ab565b949350505050565b6000806040838503121561542757600080fd5b823561543281615213565b9150602083013561544281615245565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561548e5783516001600160a01b031683529284019291840191600101615469565b50909695505050505050565b60c0815260006154ad60c08301896153ab565b60208301979097525060408101949094526060840192909252608083015260a090910152919050565b6000610220820190508d51825260208e0151602083015260408e0151604083015260608e0151606083015260808e0151608083015260a08e015160a083015261552a60c083018e6001600160a01b03169052565b8b60e08301528a6101008301528961012083015261554d61014083018a15159052565b61ffff881661016083015286610180830152856101a0830152846101c0830152836101e083015261558361020083018415159052565b9d9c50505050505050505050505050565b600080604083850312156155a757600080fd5b82356155b281615213565b946020939093013593505050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b848110156156b457603f198a8503018652825160e0815181875261560e828801826153ab565b838c0151888d01528a8401518b890152606080850151818a0152608080860151908a015260a080860151908a015260c094850151898303958a01959095528451808352948d0194879450909250908c01905b8084101561569e57845180516001600160a01b031683528d81015161ffff168e8401528c01518c830152938c01936001939093019290820190615660565b50988b01989650505092880192506001016155e8565b50919998505050505050505050565b60008060008060008060c087890312156156dc57600080fd5b86356156e781615213565b955060208701359450604087013593506060870135615705816151c6565b9250608087013561571581615245565b8092505060a087013590509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561548e57835183529284019291840191600101615746565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156157a1576157a1615762565b604052919050565b600067ffffffffffffffff8211156157c3576157c3615762565b5060051b60200190565b600082601f8301126157de57600080fd5b813560206157f36157ee836157a9565b615778565b82815260059290921b8401810191818101908684111561581257600080fd5b8286015b8481101561583657803561582981615213565b8352918301918301615816565b509695505050505050565b6000806040838503121561585457600080fd5b823567ffffffffffffffff8082111561586c57600080fd5b615878868387016157cd565b935060209150818501358181111561588f57600080fd5b85019050601f810186136158a257600080fd5b80356158b06157ee826157a9565b81815260059190911b820183019083810190888311156158cf57600080fd5b928401925b828410156158ed578335825292840192908401906158d4565b80955050505050509250929050565b600082601f83011261590d57600080fd5b8135602061591d6157ee836157a9565b82815260059290921b8401810191818101908684111561593c57600080fd5b8286015b84811015615836578035615953816151c6565b8352918301918301615940565b60008060006060848603121561597557600080fd5b833567ffffffffffffffff8082111561598d57600080fd5b818601915086601f8301126159a157600080fd5b81356020828211156159b5576159b5615762565b6159c7601f8301601f19168201615778565b82815289828487010111156159db57600080fd5b82828601838301376000928101820192909252909550860135915080821115615a0357600080fd5b615a0f878388016157cd565b93506040860135915080821115615a2557600080fd5b50615a32868287016158fc565b9150509250925092565b600080600080600060a08688031215615a5457600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680615aa157607f821691505b602082108103615ac157634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615615af757615af7615ac7565b500290565b600082615b1957634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561176b5761176b615ac7565b600060018201615b4357615b43615ac7565b5060010190565b600181815b80851115611fa3578160001904821115615b6b57615b6b615ac7565b80851615615b7857918102915b93841c9390800290615b4f565b600082615b945750600161176b565b81615ba15750600061176b565b8160018114615bb75760028114615bc157615bdd565b600191505061176b565b60ff841115615bd257615bd2615ac7565b50506001821b61176b565b5060208310610133831016604e8410600b8410161715615c00575081810a61176b565b615c0a8383615b4a565b8060001904821115615c1e57615c1e615ac7565b029392505050565b60006151f360ff841683615b85565b8181038181111561176b5761176b615ac7565b600060208284031215615c5a57600080fd5b5051919050565b600060ff821660ff8103615c7757615c77615ac7565b60010192915050565b600060208284031215615c9257600080fd5b81516151f3816151c6565b600060208284031215615caf57600080fd5b81516151f3816152bf565b80516001600160501b0381168114615cd157600080fd5b919050565b600080600080600060a08688031215615cee57600080fd5b615cf786615cba565b9450602086015193506040860151925060608601519150615d1a60808701615cba565b90509295509295909350565b600060208284031215615d3857600080fd5b81516151f381615213565b60208082526011908201527036bab9ba1037bbb7103837b9b4ba34b7b760791b604082015260600190565b600060208284031215615d8057600080fd5b81516151f381615245565b634e487b7160e01b600052603160045260246000fd5b601f82111561103e57600081815260208120601f850160051c81016020861015615dc85750805b601f850160051c820191505b81811015615de757828155600101615dd4565b505050505050565b818103615dfa575050565b615e048254615a8d565b67ffffffffffffffff811115615e1c57615e1c615762565b615e3081615e2a8454615a8d565b84615da1565b6000601f821160018114615e645760008315615e4c5750848201545b600019600385901b1c1916600184901b17845561406f565b600085815260209020601f19841690600086815260209020845b83811015615e9e5782860154825560019586019590910190602001615e7e565b5085831015615ebc5781850154600019600388901b60f8161c191681555b5050505050600190811b01905550565b815167ffffffffffffffff811115615ee657615ee6615762565b615ef481615e2a8454615a8d565b602080601f831160018114615f295760008415615f115750858301515b600019600386901b1c1916600185901b178555615de7565b600085815260208120601f198616915b82811015615f5857888601518255948401946001909101908401615f39565b5085821015615ebc57939096015160001960f8600387901b161c19169092555050600190811b01905550565b60008060408385031215615f9757600080fd5b50508051602090910151909290915056fea164736f6c6343000810000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002e68747470733a2f2f6170692e7969656c64696669636174696f6e2e636f6d2f70667964662f6d657461646174612f000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _tokenURI (string): https://api.yieldification.com/pfydf/metadata/
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 000000000000000000000000000000000000000000000000000000000000002e
Arg [2] : 68747470733a2f2f6170692e7969656c64696669636174696f6e2e636f6d2f70
Arg [3] : 667964662f6d657461646174612f000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.