Latest 25 from a total of 9,138 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw ERC20 | 161616297 | 768 days ago | IN | 0 ETH | 0.00015633 | ||||
| Withdraw ERC20 | 161616186 | 768 days ago | IN | 0 ETH | 0.00015615 | ||||
| Withdraw ERC20 | 155561040 | 787 days ago | IN | 0 ETH | 0.00007447 | ||||
| Withdraw ERC20 | 150015488 | 804 days ago | IN | 0 ETH | 0.00013272 | ||||
| Withdraw ERC20 | 132489588 | 859 days ago | IN | 0 ETH | 0.00001854 | ||||
| Withdraw ERC20 | 128357252 | 873 days ago | IN | 0 ETH | 0.00003974 | ||||
| Withdraw ERC20 | 128357085 | 873 days ago | IN | 0 ETH | 0.00004021 | ||||
| Remove Trigger O... | 89621425 | 990 days ago | IN | 0 ETH | 0.00022137 | ||||
| Remove Trigger O... | 89621330 | 990 days ago | IN | 0 ETH | 0.00022137 | ||||
| Close Position | 87715640 | 996 days ago | IN | 0 ETH | 0.00017117 | ||||
| Close Position | 87603985 | 996 days ago | IN | 0 ETH | 0.00028692 | ||||
| Close Position | 87522712 | 996 days ago | IN | 0 ETH | 0.0001516 | ||||
| Close Position | 87522298 | 996 days ago | IN | 0 ETH | 0.00015599 | ||||
| Close Position | 87522237 | 996 days ago | IN | 0 ETH | 0.00015599 | ||||
| Close Position | 87044160 | 998 days ago | IN | 0 ETH | 0.00012786 | ||||
| Add Trigger Orde... | 87009665 | 998 days ago | IN | 0 ETH | 0.0001533 | ||||
| Close Position | 85789333 | 1001 days ago | IN | 0 ETH | 0.00007763 | ||||
| Settle Unsettled... | 85202271 | 1003 days ago | IN | 0 ETH | 0.00010692 | ||||
| Close Position | 85201518 | 1003 days ago | IN | 0 ETH | 0.0001002 | ||||
| Open Position | 85166653 | 1003 days ago | IN | 0 ETH | 0.00010582 | ||||
| Add Trigger Orde... | 85147511 | 1003 days ago | IN | 0 ETH | 0.00007391 | ||||
| Remove Trigger O... | 85147391 | 1003 days ago | IN | 0 ETH | 0.0000647 | ||||
| Close Position | 85114811 | 1003 days ago | IN | 0 ETH | 0.00007912 | ||||
| Add Trigger Orde... | 85057393 | 1004 days ago | IN | 0 ETH | 0.00007209 | ||||
| Open Position | 85013503 | 1004 days ago | IN | 0 ETH | 0.00016453 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 72084009 | 1041 days ago | 0 ETH | ||||
| 72084009 | 1041 days ago | 0 ETH | ||||
| 72084009 | 1041 days ago | 0 ETH | ||||
| 72084009 | 1041 days ago | 0 ETH | ||||
| 72084009 | 1041 days ago | 0 ETH | ||||
| 72084009 | 1041 days ago | 0 ETH | ||||
| 72084009 | 1041 days ago | 0 ETH | ||||
| 72084009 | 1041 days ago | 0 ETH | ||||
| 72084009 | 1041 days ago | 0 ETH | ||||
| 72084009 | 1041 days ago | 0 ETH | ||||
| 72084009 | 1041 days ago | 0 ETH | ||||
| 72063073 | 1041 days ago | 0 ETH | ||||
| 72063073 | 1041 days ago | 0 ETH | ||||
| 72063073 | 1041 days ago | 0 ETH | ||||
| 72063073 | 1041 days ago | 0 ETH | ||||
| 72062783 | 1041 days ago | 0 ETH | ||||
| 72044844 | 1041 days ago | 0 ETH | ||||
| 72044844 | 1041 days ago | 0 ETH | ||||
| 72044844 | 1041 days ago | 0 ETH | ||||
| 72044844 | 1041 days ago | 0 ETH | ||||
| 72043790 | 1041 days ago | 0 ETH | ||||
| 72042001 | 1041 days ago | 0 ETH | ||||
| 72042001 | 1041 days ago | 0 ETH | ||||
| 72042001 | 1041 days ago | 0 ETH | ||||
| 72042001 | 1041 days ago | 0 ETH |
Cross-Chain Transactions
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/token/ERC20/ERC20.sol';
import '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
import './interfaces/IFeeReducer.sol';
import './interfaces/IBokkyPooBahsDateTime.sol';
import './IndexHandler.sol';
import './pfYDF.sol';
contract PerpetualFutures is IndexHandler, KeeperCompatibleInterface, Ownable {
using SafeERC20 for ERC20;
uint256 constant PERC_DEN = 100000;
pfYDF perpsNft;
IFeeReducer feeReducer;
IBokkyPooBahsDateTime timeLibrary =
IBokkyPooBahsDateTime(0x23d23d8F243e57d0b924bff3A3191078Af325101);
bool public tradingEnabled;
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
// 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 getFeeReducer() external view returns (address) {
return address(feeReducer);
}
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 _desiredPrice,
uint256 _slippage, // 1 == 0.1%, 10 == 1%
uint256 _collateral,
uint16 _leverage, // 10 == 1x, 1000 == 100x
bool _isLong,
uint256 _triggerOrderTargetPrice
) external payable {
require(tradingEnabled, 'DISABLED');
require(_indexInd < indexes.length, 'INVIDX');
require(_leverage >= 10 && _leverage <= maxLeverage, 'LEV1');
require(_canOpenAgainstIndex(_indexInd, 0), 'INDOOB1');
require(
_collToken == address(0) ||
_collToken == mainCollateralToken ||
_validColl[_collToken],
'POSTOKEN1'
);
uint256 _newTokenId = perpsNft.mint(msg.sender);
(uint256 _openFee, uint256 _finalCollateral) = _processOpenCollateral(
msg.sender,
_collToken,
_collateral,
_leverage
);
Position storage _newPosition = _createNewPosition(_indexInd, _newTokenId);
uint256 _openPrice = getIndexPriceFromIndex(_indexInd);
_validateOpenPriceSlip(_desiredPrice, _openPrice, _slippage, _isLong);
positionOpeners[_newTokenId] = msg.sender;
_newPosition.lifecycle.openTime = block.timestamp;
_newPosition.lifecycle.openFees = _openFee;
_newPosition.collateralAmount = _finalCollateral;
_newPosition.positionAmount = (_finalCollateral * _leverage) / 10;
_newPosition.isLong = _isLong;
_newPosition.leverage = _leverage;
_newPosition.indexPriceStart = _openPrice;
_newPosition.collateralToken = _collToken;
_addOpenPosition(_newTokenId);
_validateAndUpdateOpenAmounts(_newTokenId, _newPosition.positionAmount);
if (_triggerOrderTargetPrice > 0) {
_addTriggerOrder(_newTokenId, _triggerOrderTargetPrice);
}
emit OpenPosition(
_newTokenId,
msg.sender,
_openPrice,
_finalCollateral,
_isLong,
_leverage
);
}
function _processOpenCollateral(
address _user,
address _collToken,
uint256 _collateral,
uint256 _leverage
) internal returns (uint256, uint256) {
uint256 _openFee;
uint256 _finalCollateral;
// native token
if (_collToken == address(0)) {
require(msg.value > 0, 'COLL3');
_collateral = msg.value;
_openFee = _getPositionOpenFee(_user, _collateral, _leverage);
_finalCollateral = _collateral - _openFee;
} else {
ERC20 _collCont = ERC20(_collToken);
require(_collCont.balanceOf(_user) >= _collateral, 'BAL1');
uint256 _before = _collCont.balanceOf(address(this));
_collCont.safeTransferFrom(_user, address(this), _collateral);
_collateral = _collCont.balanceOf(address(this)) - _before;
_openFee = _getPositionOpenFee(_user, _collateral, _leverage);
_finalCollateral = _collateral - _openFee;
}
return (_openFee, _finalCollateral);
}
function _validateOpenPriceSlip(
uint256 _desiredPrice,
uint256 _currentPrice,
uint256 _slippage, // 1 == 0.1%, 10 == 1%
bool _isLong
) internal pure {
uint256 _idxSlipDiff;
if (_isLong && _currentPrice > _desiredPrice) {
_idxSlipDiff = _currentPrice - _desiredPrice;
} else if (!_isLong && _desiredPrice > _currentPrice) {
_idxSlipDiff = _desiredPrice - _currentPrice;
}
if (_idxSlipDiff > 0) {
require(
(_idxSlipDiff * FACTOR) / _desiredPrice <= (_slippage * FACTOR) / 1000,
'SLIPPAGE'
);
}
}
function _createNewPosition(uint256 _indexInd, uint256 _tokenId)
internal
returns (Position storage)
{
Position storage _newPosition = positions[_tokenId];
for (uint256 _i = 0; _i < indexes[_indexInd].priceFeeds.length; _i++) {
(uint16 _phase, uint80 _round, ) = getLatestProxyInfo(
indexes[_indexInd].priceFeeds[_i].proxy
);
_newPosition.feeds.push(
PositionIndexFeed({
feed: indexes[_indexInd].priceFeeds[_i],
phaseIdStart: _phase,
roundIdStart: _round,
phaseIdSettle: 0,
roundIdSettle: 0
})
);
}
return _newPosition;
}
function _canOpenAgainstIndex(uint256 _ind, uint256 _timestamp)
internal
view
returns (bool)
{
return
_doTimeBoundsPass(
_timestamp,
indexes[_ind].dowOpenMin,
indexes[_ind].dowOpenMax,
indexes[_ind].hourOpenMin,
indexes[_ind].hourOpenMax
);
}
function _doTimeBoundsPass(
uint256 _timestamp,
uint256 _dowOpenMin,
uint256 _dowOpenMax,
uint256 _hourOpenMin,
uint256 _hourOpenMax
) internal view returns (bool) {
_timestamp = _timestamp == 0 ? block.timestamp : _timestamp;
if (_dowOpenMin >= 1 && _dowOpenMax >= 1) {
uint256 _dow = timeLibrary.getDayOfWeek(_timestamp);
if (_dow < _dowOpenMin || _dow > _dowOpenMax) {
return false;
}
}
if (_hourOpenMin >= 1 || _hourOpenMax >= 1) {
uint256 _hour = timeLibrary.getHour(_timestamp);
if (_hour < _hourOpenMin || _hour > _hourOpenMax) {
return false;
}
}
return true;
}
function closePosition(uint256 _tokenId) external {
_closePosition(_tokenId, false);
}
function _closePosition(uint256 _tokenId, bool _overrideOwner) internal {
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,
positions[_tokenId].indexPriceStart,
positions[_tokenId].indexPriceSettle,
positions[_tokenId].amountWon,
positions[_tokenId].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**ERC20(mainCollateralToken).decimals() *
_collPriceUSD) /
_mainPriceUSD /
10**ERC20(_position.collateralToken).decimals();
ERC20(mainCollateralToken).safeTransfer(
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)
{
address[] memory _proxies = new address[](positions[_tokenId].feeds.length);
uint256[] memory _multipliers = new uint256[](
positions[_tokenId].feeds.length
);
for (uint256 _i = 0; _i < positions[_tokenId].feeds.length; _i++) {
_proxies[_i] = positions[_tokenId].feeds[_i].feed.proxy;
_multipliers[_i] = positions[_tokenId].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)
{
address[] memory _proxies = new address[](positions[_tokenId].feeds.length);
for (uint256 _i = 0; _i < positions[_tokenId].feeds.length; _i++) {
_proxies[_i] = positions[_tokenId].feeds[_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 setOpenFeePositionSize(uint256 _percentage) external onlyOwner {
require(_percentage < (PERC_DEN * 10) / 100, 'max 10%');
openFeePositionSize = _percentage;
}
function setCloseFeePositionSize(uint256 _percentage) external onlyOwner {
require(_percentage < (PERC_DEN * 10) / 100, 'max 10%');
closeFeePositionSize = _percentage;
}
function setCloseFeePositionPerDurationUnit(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 setTradingEnabled(bool _tradingEnabled) external onlyOwner {
tradingEnabled = _tradingEnabled;
}
function setFeeReducer(address _reducer) external onlyOwner {
feeReducer = IFeeReducer(_reducer);
}
function processFees(uint256 _amount) external onlyOwner {
ERC20(mainCollateralToken).safeTransfer(mainCollateralToken, _amount);
}
function withdrawERC20(address _token, uint256 _amount) external onlyOwner {
ERC20 _contract = ERC20(_token);
_amount = _amount == 0 ? _contract.balanceOf(address(this)) : _amount;
require(_amount > 0);
_contract.safeTransfer(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 _wasLiquidated = checkAndLiquidatePosition(_tokenId);
if (_wasLiquidated) {
_liquidations++;
if (_liquidations >= maxLiquidationsPerUpkeep) {
break;
}
}
}
}
function checkAndLiquidatePosition(uint256 _tokenId) public returns (bool) {
bool _shouldLiquidate = shouldPositionLiquidate(_tokenId);
bool _triggerClose = shouldPositionCloseFromTrigger(_tokenId);
if (_shouldLiquidate || _triggerClose) {
_closePosition(_tokenId, true);
if (_shouldLiquidate) {
emit LiquidatePosition(_tokenId);
} else if (_triggerClose) {
emit ClosePositionFromTriggerOrder(_tokenId);
}
return true;
}
return false;
}
function getFeeDiscount(address _wallet)
public
view
returns (uint256, uint256)
{
return
address(feeReducer) != address(0)
? feeReducer.percentDiscount(_wallet)
: (0, 0);
}
function _getPositionOpenFee(
address _user,
uint256 _collateral,
uint256 _leverage
) internal view returns (uint256) {
uint256 _positionPreFee = (_collateral * _leverage) / 10;
uint256 _openFee = (_positionPreFee * openFeePositionSize) / PERC_DEN;
(uint256 _percentOff, uint256 _percOffDenomenator) = getFeeDiscount(_user);
// 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;
ERC20(_position.collateralToken).safeTransfer(
_closingUser,
_returnAmount
);
} else {
if (_returnAmount > _position.collateralAmount) {
if (_position.collateralToken == address(0)) {
uint256 _before = address(this).balance;
payable(_closingUser).call{ value: _position.collateralAmount }('');
require(
address(this).balance >= _before - _position.collateralAmount,
'NAT1'
);
} else {
ERC20(_position.collateralToken).safeTransfer(
_closingUser,
_position.collateralAmount
);
}
_position.collateralCloseUnsettled =
_returnAmount -
_position.collateralAmount;
_unsettledPositionsIdx[_tokenId] = allUnsettledPositions.length;
allUnsettledPositions.push(_tokenId);
emit CloseUnsettledPosition(_tokenId);
} else {
_position.isSettled = true;
if (_position.collateralToken == address(0)) {
uint256 _before = address(this).balance;
payable(_closingUser).call{ value: _returnAmount }('');
require(address(this).balance >= _before - _returnAmount, 'NAT1');
} else {
ERC20(_position.collateralToken).safeTransfer(
_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;
(
uint256 _currentIndexPrice,
uint256 _amountReturnToUser,
uint256 _absolutePL,
bool _isProfit,
bool _canCloseInProfit
) = getIndexAndPLInfo(_tokenId);
// 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 {
// update settle phase and round data for all proxies that make up the index
for (uint256 _i = 0; _i < positions[_tokenId].feeds.length; _i++) {
PositionIndexFeed storage _feed = positions[_tokenId].feeds[_i];
(uint16 _phase, uint80 _round, ) = getLatestProxyInfo(_feed.feed.proxy);
_feed.phaseIdSettle = _phase;
_feed.roundIdSettle = _round;
}
}
function _validateAndUpdateOpenAmounts(uint256 _tokenId, uint256 _amount)
internal
{
if (positions[_tokenId].isLong) {
amtOpenLong[positions[_tokenId].collateralToken] += _amount;
} else {
amtOpenShort[positions[_tokenId].collateralToken] += _amount;
}
if (maxCollateralOpenDiff[positions[_tokenId].collateralToken] > 0) {
uint256 _openDiff = amtOpenLong[positions[_tokenId].collateralToken] >
amtOpenShort[positions[_tokenId].collateralToken]
? amtOpenLong[positions[_tokenId].collateralToken] -
amtOpenShort[positions[_tokenId].collateralToken]
: amtOpenShort[positions[_tokenId].collateralToken] -
amtOpenLong[positions[_tokenId].collateralToken];
require(
_openDiff <= maxCollateralOpenDiff[positions[_tokenId].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)
{
uint256 _priceChangeForLiquidation = getLiquidationPriceChange(_tokenId);
(uint256 _closingFeeMain, uint256 _closingFeeTime) = getPositionCloseFees(
_tokenId
);
(
uint256 _currentIndexPrice,
uint256 _amountReturnToUser,
,
bool _isProfit,
) = getIndexAndPLInfo(_tokenId);
uint256 _indexPriceDelinquencyPrice = positions[_tokenId].isLong
? positions[_tokenId].indexPriceStart - _priceChangeForLiquidation
: positions[_tokenId].indexPriceStart + _priceChangeForLiquidation;
bool _priceInLiquidation = positions[_tokenId].isLong
? _currentIndexPrice <= _indexPriceDelinquencyPrice
: _currentIndexPrice >= _indexPriceDelinquencyPrice;
bool _feesExceedReturn = !_isProfit &&
_closingFeeMain + _closingFeeTime >= _amountReturnToUser;
return _priceInLiquidation || _feesExceedReturn;
}
function shouldPositionCloseFromTrigger(uint256 _tokenId)
public
view
returns (bool)
{
uint256 _currIdxPrice = getPositionIndexPrice(_tokenId);
for (uint256 _i = 0; _i < positionTriggerOrders[_tokenId].length; _i++) {
uint256 _target = positionTriggerOrders[_tokenId][_i].idxPriceTarget;
bool _lessThanEQ = _target <
positionTriggerOrders[_tokenId][_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 (last updated v4.7.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @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, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been 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 _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
interface IFeeReducer {
function percentDiscount(address wallet)
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
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (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
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 v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol";
// 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/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
Contract ABI
API[{"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":"_tokenId","type":"uint256"}],"name":"checkAndLiquidatePosition","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","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":"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":"address","name":"_wallet","type":"address"}],"name":"getFeeDiscount","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeeReducer","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":"_desiredPrice","type":"uint256"},{"internalType":"uint256","name":"_slippage","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":"payable","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":"_seconds","type":"uint256"}],"name":"setCloseFeePositionPerDurationUnit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percentage","type":"uint256"}],"name":"setCloseFeePositionSize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_percentage","type":"uint256"}],"name":"setClosePositionFeePerDuration","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":"setOpenFeePositionSize","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":"bool","name":"_tradingEnabled","type":"bool"}],"name":"setTradingEnabled","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":"tradingEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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
6080604052600480547323d23d8f243e57d0b924bff3a3191078af3251016001600160a01b0319909116179055600680546001600160a81b0319167430dcba0405004cf124045793e1933c798af9e66a19179055600a805462ffffff1916620201f4179055612a30600b556103e86200007d620186a0600f62000240565b6200008991906200026e565b600c556103e86200009f620186a0600162000240565b620000ab91906200026e565b600d556103e8620000c1620186a0600162000240565b620000cd91906200026e565b600e55610e10600f55620186a0620000e781600562000240565b620000f391906200026e565b6010553480156200010357600080fd5b5060405162008976380380620089768339810160408190526200012691620002cd565b6200013133620001e0565b80604051620001409062000232565b6200014c919062000385565b604051809103906000f08015801562000169573d6000803e3d6000fd5b50600280546001600160a01b0319166001600160a01b0392909216918217905560405163f2fde38b60e01b815233600482015263f2fde38b90602401600060405180830381600087803b158015620001c057600080fd5b505af1158015620001d5573d6000803e3d6000fd5b5050505050620003ba565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6126c180620062b583390190565b60008160001904831182151516156200026957634e487b7160e01b600052601160045260246000fd5b500290565b6000826200028c57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620002c4578181015183820152602001620002aa565b50506000910152565b600060208284031215620002e057600080fd5b81516001600160401b0380821115620002f857600080fd5b818401915084601f8301126200030d57600080fd5b81518181111562000322576200032262000291565b604051601f8201601f19908116603f011681019083821181831017156200034d576200034d62000291565b816040528281528760208487010111156200036757600080fd5b6200037a836020830160208801620002a7565b979650505050505050565b6020815260008251806020840152620003a6816040850160208701620002a7565b601f01601f19169190910160400192915050565b615eeb80620003ca6000396000f3fe6080604052600436106104105760003560e01c80638da5cb5b1161021e578063cb03890711610123578063e03527d5116100ab578063f2fde38b1161007a578063f2fde38b14610e1f578063f53d9ec114610e3f578063f707159714610e5f578063fd5891c414610e7f578063fffa41b114610e9f57600080fd5b8063e03527d514610d9f578063e34274ef14610dbf578063e867d90414610ddf578063ee9b802714610dff57600080fd5b8063d5e34836116100f2578063d5e3483614610d0a578063d834123e14610d2a578063dc73131814610d4a578063dcb03dc614610d6a578063df72ad2714610d7d57600080fd5b8063cb03890714610c9e578063d14d40bb14610cbe578063d19529ff14610cd4578063d2c76d7414610cea57600080fd5b8063ae3302c2116101a6578063b91d08ce11610175578063b91d08ce14610bfa578063ba93fd9014610c1a578063bd4bf07a14610c30578063c2e5ec0414610c4e578063c70a900f14610c6e57600080fd5b8063ae3302c214610b61578063b54710e714610b8f578063b7fa7cfc14610baf578063b81bb71014610be457600080fd5b806396e61bc7116101ed57806396e61bc7146109e357806399fbab8814610a19578063a126d60114610aff578063a1db978214610b1f578063a2f0a1f214610b3f57600080fd5b80638da5cb5b146109515780638f0525ec1461096f57806391bb214b1461098f57806392f8eb94146109b157600080fd5b8063594a60ae116103245780636c9963f4116102ac5780637c011be81161027b5780637c011be8146108a95780637f3b7a02146108c957806384a43170146108df578063861d1dfa146108ff57806389701db51461093157600080fd5b80636c9963f4146108265780636e04ff0d14610846578063715018a61461087457806377a354651461088957600080fd5b806362c7536d116102f357806362c7536d1461076c57806365f290f714610799578063667073fc146107c657806366c62643146107e65780636b4b68661461080657600080fd5b8063594a60ae146106ec5780635ad15eda1461070c5780635ba873101461072c5780635bc412d91461074c57600080fd5b806339d99cca116103a757806348bb4e331161037657806348bb4e33146106285780634ada218b146106485780634dfdeee5146106695780634f8f53321461067f57806358920140146106a457600080fd5b806339d99cca146105925780633a2baafd146105b25780633f08e526146105e85780634585e33b1461060857600080fd5b8063182d8747116103e3578063182d8747146104c95780631a090154146104f95780631a79344c14610519578063335db3061461056557600080fd5b80630679d362146104155780630f1627931461043757806310edc9801461046a578063174b63991461049c575b600080fd5b34801561042157600080fd5b506104356104303660046150d9565b610ebf565b005b34801561044357600080fd5b506104576104523660046150f6565b610f25565b6040519081526020015b60405180910390f35b34801561047657600080fd5b506002546001600160a01b03165b6040516001600160a01b039091168152602001610461565b3480156104a857600080fd5b506104576104b7366004615124565b60136020526000908152604090205481565b3480156104d557600080fd5b506104e96104e43660046150f6565b611148565b6040519015158152602001610461565b34801561050557600080fd5b506104356105143660046150f6565b61122f565b34801561052557600080fd5b506105396105343660046150f6565b611382565b60408051958652602086019490945292840191909152151560608301521515608082015260a001610461565b34801561057157600080fd5b506105856105803660046150f6565b6116a3565b6040516104619190615141565b34801561059e57600080fd5b506104356105ad36600461519f565b611729565b3480156105be57600080fd5b506104846105cd3660046150f6565b6015602052600090815260409020546001600160a01b031681565b3480156105f457600080fd5b506104356106033660046150f6565b611782565b34801561061457600080fd5b506104356106233660046151bc565b6117cb565b34801561063457600080fd5b5061043561064336600461519f565b61184f565b34801561065457600080fd5b506004546104e990600160a01b900460ff1681565b34801561067557600080fd5b50610457600c5481565b34801561068b57600080fd5b506006546104849061010090046001600160a01b031681565b3480156106b057600080fd5b506106c46106bf366004615124565b611875565b6040805161ffff90941684526001600160501b03909216602084015290820152606001610461565b3480156106f857600080fd5b5061043561070736600461522e565b6119f3565b34801561071857600080fd5b506104e96107273660046150f6565b611a9b565b34801561073857600080fd5b506104576107473660046150f6565b611b8c565b34801561075857600080fd5b506104356107673660046150f6565b611bad565b34801561077857600080fd5b50610457610787366004615124565b60126020526000908152604090205481565b3480156107a557600080fd5b506104576107b4366004615124565b60116020526000908152604090205481565b3480156107d257600080fd5b506104e96107e13660046150f6565b611c0b565b3480156107f257600080fd5b506104356108013660046150f6565b611cc1565b34801561081257600080fd5b5061043561082136600461525a565b611d1f565b34801561083257600080fd5b506104356108413660046150f6565b611dc6565b34801561085257600080fd5b506108666108613660046151bc565b611e25565b6040516104619291906152cc565b34801561088057600080fd5b50610435611e9a565b34801561089557600080fd5b506104356108a43660046152f5565b611eae565b3480156108b557600080fd5b506104356108c436600461525a565b611f3a565b3480156108d557600080fd5b50610457600e5481565b3480156108eb57600080fd5b506104356108fa3660046150f6565b611fe1565b34801561090b57600080fd5b50600a5461091f9062010000900460ff1681565b60405160ff9091168152602001610461565b34801561093d57600080fd5b5061043561094c3660046150f6565b612040565b34801561095d57600080fd5b506001546001600160a01b0316610484565b34801561097b57600080fd5b5061045761098a3660046150f6565b612067565b34801561099b57600080fd5b506109a46120a6565b604051610461919061532e565b3480156109bd57600080fd5b506109d16109cc3660046150f6565b612108565b6040516104619695949392919061536f565b3480156109ef57600080fd5b506104846109fe3660046150f6565b6016602052600090815260409020546001600160a01b031681565b348015610a2557600080fd5b50610ae7610a343660046150f6565b601460209081526000918252604091829020825160c081018452600182015481526002820154928101929092526003810154928201929092526004820154606082015260058201546080820152600682015460a0820152600782015460088301546009840154600a850154600b860154600c870154600d880154600e890154600f8a01546010909a015498996001600160a01b039098169896979596949560ff8086169661010090960461ffff1695168c565b6040516104619c9b9a999897969594939291906153ab565b348015610b0b57600080fd5b50610435610b1a3660046150f6565b6121dc565b348015610b2b57600080fd5b50610435610b3a366004615469565b6121e7565b348015610b4b57600080fd5b50610b54612299565b6040516104619190615495565b348015610b6d57600080fd5b50600a54610b7c9061ffff1681565b60405161ffff9091168152602001610461565b348015610b9b57600080fd5b506109a4610baa3660046150f6565b612444565b348015610bbb57600080fd5b50610bcf610bca366004615124565b612536565b60408051928352602083019190915201610461565b348015610bf057600080fd5b50610457600f5481565b348015610c0657600080fd5b50610457610c153660046150f6565b6125c9565b348015610c2657600080fd5b50610457600d5481565b348015610c3c57600080fd5b506003546001600160a01b0316610484565b348015610c5a57600080fd5b50610435610c69366004615598565b6125d9565b348015610c7a57600080fd5b506104e9610c89366004615124565b60056020526000908152604090205460ff1681565b348015610caa57600080fd5b50610435610cb93660046150f6565b6125ff565b348015610cca57600080fd5b5061045760105481565b348015610ce057600080fd5b50610457600b5481565b348015610cf657600080fd5b50610435610d05366004615469565b61264c565b348015610d1657600080fd5b50610bcf610d253660046150f6565b612670565b348015610d3657600080fd5b50610435610d45366004615124565b6127e7565b348015610d5657600080fd5b50610bcf610d6536600461525a565b612811565b610435610d783660046155b5565b61284d565b348015610d8957600080fd5b50610d92612be9565b6040516104619190615631565b348015610dab57600080fd5b50610435610dba36600461522e565b612c40565b348015610dcb57600080fd5b50610457610dda3660046150f6565b612f93565b348015610deb57600080fd5b50610435610dfa366004615124565b613135565b348015610e0b57600080fd5b50610435610e1a3660046152f5565b6131a0565b348015610e2b57600080fd5b50610435610e3a366004615124565b613364565b348015610e4b57600080fd5b50610435610e5a3660046150f6565b6133da565b348015610e6b57600080fd5b50610457610e7a366004615748565b6134fb565b348015610e8b57600080fd5b50610435610e9a366004615867565b6135a8565b348015610eab57600080fd5b50610435610eba366004615943565b613805565b610ec7613850565b6109c48161ffff161115610f0d5760405162461bcd60e51b81526020600482015260086024820152670dac2f040646a60f60c31b60448201526064015b60405180910390fd5b600a805461ffff191661ffff92909216919091179055565b60008060008381548110610f3b57610f3b61597e565b90600052602060002090600702016040518060e0016040529081600082018054610f6490615994565b80601f0160208091040260200160405190810160405280929190818152602001828054610f9090615994565b8015610fdd5780601f10610fb257610100808354040283529160200191610fdd565b820191906000526020600020905b815481529060010190602001808311610fc057829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201805480602002602001604051908101604052809291908181526020016000905b82821015611098576000848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b900461ffff168385015260019081015491830191909152908352909201910161103d565b50505091525090915060009050805b8260c00151518110156111405760008360c0015182815181106110cc576110cc61597e565b6020026020010151905060006110e58260000151611875565b92505050816040015160001461111d57670de0b6b3a764000082604001518261110e91906159e4565b6111189190615a03565b61111f565b805b6111299085615a25565b93505050808061113890615a38565b9150506110a7565b509392505050565b60008061115483612f93565b905060005b60008481526017602052604090205481101561122557600084815260176020526040812080548390811061118f5761118f61597e565b906000526020600020906002020160010154905060006017600087815260200190815260200160002083815481106111c9576111c961597e565b9060005260206000209060020201600001548210905080156111fd578184116111f85750600195945050505050565b611210565b8184106112105750600195945050505050565b5050808061121d90615a38565b915050611159565b5060009392505050565b611237613850565b600080828154811061124b5761124b61597e565b90600052602060002090600702019050600181600601805490501161129a5760405162461bcd60e51b8152602060048201526005602482015264092a69288b60db1b6044820152606401610f04565b60005b600682015481101561137d5760006112e28360060183815481106112c3576112c361597e565b60009182526020909120600290910201546001600160a01b0316611875565b92505050806002670de0b6b3a76400006112fc9190615b2d565b8460060184815481106113115761131161597e565b60009182526020909120600290910201546113379190600160a01b900461ffff166159e4565b6113419190615a03565b8360060183815481106113565761135661597e565b6000918252602090912060016002909202010155508061137581615a38565b91505061129d565b505050565b60008060008060008060146000888152602001908152602001600020604051806101a001604052908160008201805480602002602001604051908101604052809291908181526020016000905b8282101561147657600084815260209081902060408051610100810182526003860290920180546001600160a01b03811660a0850190815261ffff600160a01b909204821660c086015260018084015460e0870152908552600290920154808216858701526001600160501b03620100008204811694860194909452600160601b81049091166060850152600160701b9004909116608083015290835290920191016113cf565b505050908252506040805160c080820183526001858101548352600286015460208481019190915260038701548486015260048701546060808601919091526005880154608080870191909152600689015460a0808801919091529288019590955260078801546001600160a01b031695870195909552600887015494860194909452600986015492850192909252600a85015492840192909252600b84015460ff80821615159385019390935261ffff610100918290041660e0850152600c85015490840152600d840154610120840152600e840154610140840152600f84015461016084015260109093015416151561018090910152909150600061157c89612f93565b6101008401519091508082119082106000826115a857838661010001516115a39190615b3c565b6115b8565b6101008601516115b89085615b3c565b90506000866101000151828860a001516115d291906159e4565b6115dc9190615a03565b905060008760c001516115ef57836115f1565b845b6080890151909150811561166f576000620186a0600c548b610100015161161891906159e4565b6116229190615a03565b85101590506000600b548b602001516000015161163f9190615a25565b4210159050818061164d5750805b156116635761165c8584615a25565b9250611668565b600099505b505061168c565b8083111561167f5750600061168c565b6116898382615b3c565b90505b959e959d50909b5099509397509195505050505050565b606060176000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561171e578382906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906116d8565b505050509050919050565b611731613850565b60008160ff161161176c5760405162461bcd60e51b81526020600482015260056024820152646d696e203160d81b6044820152606401610f04565b6006805460ff191660ff92909216919091179055565b61178a613850565b6102588110156117c65760405162461bcd60e51b81526020600482015260076024820152666d696e2031306d60c81b6044820152606401610f04565b600f55565b6000805b601854811015611849576000601882815481106117ee576117ee61597e565b90600052602060002001549050600061180682611c0b565b90508015611834578361181881615b4f565b60065490955060ff908116908616109050611834575050611849565b5050808061184190615a38565b9150506117cf565b50505050565b611857613850565b600a805460ff909216620100000262ff000019909216919091179055565b6000806000808490506000816001600160a01b03166358303b106040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e29190615b6e565b90506000826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611924573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119489190615b8b565b9050600080846001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561198b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119af9190615bc4565b50505091509150838284600a6119c59190615b2d565b6119d790670de0b6b3a7640000615a03565b6119e190846159e4565b97509750975050505050509193909250565b6002546040516331a9108f60e11b81526004810185905284916001600160a01b031690636352211e90602401602060405180830381865afa158015611a3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a609190615c14565b6001600160a01b0316336001600160a01b031614611a905760405162461bcd60e51b8152600401610f0490615c31565b6118498484846138aa565b600080611aa783612067565b9050600080611ab585612670565b915091506000806000611ac788611382565b5060008c8152601460205260408120600b01549497509295509350909160ff169050611b0f576000898152601460205260409020600c0154611b0a908890615a25565b611b2c565b6000898152601460205260409020600c0154611b2c908890615b3c565b60008a8152601460205260408120600b01549192509060ff16611b525781851015611b57565b818511155b9050600083158015611b72575084611b6f888a615a25565b10155b90508180611b7d5750805b9b9a5050505050505050505050565b601a8181548110611b9c57600080fd5b600091825260209091200154905081565b611bb5613850565b6064611bc5620186a060016159e4565b611bcf9190615a03565b8110611c065760405162461bcd60e51b81526020600482015260066024820152656d617820312560d01b6044820152606401610f04565b601055565b600080611c1783611a9b565b90506000611c2484611148565b90508180611c2f5750805b1561122557611c3f84600161396d565b8115611c7d576040518481527feb7f91469bb290996747407607c0d2bf6b0d11afb8d5ada15dd2269709879eaf9060200160405180910390a1611cb7565b8015611cb7576040518481527fb2f224dd9601ae969b3a64ea0493482e0eead1fa818bc855679c3ad666ea1fef9060200160405180910390a15b5060019392505050565b611cc9613850565b6064611cd9620186a060036159e4565b611ce39190615a03565b8110611d1a5760405162461bcd60e51b81526020600482015260066024820152656d617820332560d01b6044820152606401610f04565b600c55565b6002546040516331a9108f60e11b81526004810184905283916001600160a01b031690636352211e90602401602060405180830381865afa158015611d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8c9190615c14565b6001600160a01b0316336001600160a01b031614611dbc5760405162461bcd60e51b8152600401610f0490615c31565b61137d8383613bdf565b611dce613850565b6064611dde620186a0600a6159e4565b611de89190615a03565b8110611e205760405162461bcd60e51b81526020600482015260076024820152666d61782031302560c81b6044820152606401610f04565b600d55565b6000606060005b601854811015611e9257600060188281548110611e4b57611e4b61597e565b90600052602060002001549050611e6181611a9b565b80611e705750611e7081611148565b15611e7f576001935050611e92565b5080611e8a81615a38565b915050611e2c565b509250929050565b611ea2613850565b611eac6000613c9d565b565b611eb6613850565b6001600160a01b03821660009081526005602052604090205481151560ff909116151503611f0f5760405162461bcd60e51b8152600401610f04906020808252600490820152635345543360e01b604082015260600190565b6001600160a01b03919091166000908152600560205260409020805460ff1916911515919091179055565b6002546040516331a9108f60e11b81526004810184905283916001600160a01b031690636352211e90602401602060405180830381865afa158015611f83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa79190615c14565b6001600160a01b0316336001600160a01b031614611fd75760405162461bcd60e51b8152600401610f0490615c31565b61137d8383613cef565b611fe9613850565b6064611ff9620186a0600a6159e4565b6120039190615a03565b811061203b5760405162461bcd60e51b81526020600482015260076024820152666d61782031302560c81b6044820152606401610f04565b600e55565b612048613850565b6006546120649061010090046001600160a01b03168083613dfc565b50565b6000818152601460205260408120600b810154600c9091015461010090910461ffff16906120969060096159e4565b6120a09190615a03565b92915050565b606060088054806020026020016040519081016040528092919081815260200182805480156120fe57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116120e0575b5050505050905090565b6000818154811061211857600080fd5b906000526020600020906007020160009150905080600001805461213b90615994565b80601f016020809104026020016040519081016040528092919081815260200182805461216790615994565b80156121b45780601f10612189576101008083540402835291602001916121b4565b820191906000526020600020905b81548152906001019060200180831161219757829003601f168201915b5050505050908060010154908060020154908060030154908060040154908060050154905086565b61206481600061396d565b6121ef613850565b8181156121fc5781612264565b6040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa158015612240573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122649190615c5c565b91506000821161227357600080fd5b61137d6122886001546001600160a01b031690565b6001600160a01b0383169084613dfc565b60606000805480602002602001604051908101604052809291908181526020016000905b8282101561243b57838290600052602060002090600702016040518060e00160405290816000820180546122f090615994565b80601f016020809104026020016040519081016040528092919081815260200182805461231c90615994565b80156123695780601f1061233e57610100808354040283529160200191612369565b820191906000526020600020905b81548152906001019060200180831161234c57829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201805480602002602001604051908101604052809291908181526020016000905b82821015612424576000848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b900461ffff16838501526001908101549183019190915290835290920191016123c9565b5050505081525050815260200190600101906122bd565b50505050905090565b6000818152601460205260408120546060919067ffffffffffffffff81111561246f5761246f615669565b604051908082528060200260200182016040528015612498578160200160208202803683370190505b50905060005b60008481526014602052604090205481101561252f5760008481526014602052604090208054829081106124d4576124d461597e565b600091825260209091206003909102015482516001600160a01b03909116908390839081106125055761250561597e565b6001600160a01b03909216602092830291909101909101528061252781615a38565b91505061249e565b5092915050565b60035460009081906001600160a01b0316612553576000806125c0565b60035460405163a310e73960e01b81526001600160a01b0385811660048301529091169063a310e739906024016040805180830381865afa15801561259c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c09190615c75565b91509150915091565b60188181548110611b9c57600080fd5b6125e1613850565b60048054911515600160a01b0260ff60a01b19909216919091179055565b612607613850565b620151808111156126475760405162461bcd60e51b815260206004820152600a6024820152696d61782031206461797360b01b6044820152606401610f04565b600b55565b612654613850565b6001600160a01b03909116600090815260136020526040902055565b6002546040516331a9108f60e11b815260048101839052600091829182916001600160a01b031690636352211e90602401602060405180830381865afa1580156126be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e29190615c14565b90506000806126f083612536565b600e546000898152601460205260408120600a01549395509193509091620186a09161271b916159e4565b6127259190615a03565b6010546000898152601460205260408120600a015492935091620186a09161274c916159e4565b6127569190615a03565b600f5460008a815260146020526040812060010154929350916127799042615b3c565b61278390846159e4565b61278d9190615a03565b905084156127d857836127a086856159e4565b6127aa9190615a03565b6127b49084615b3c565b9250836127c186836159e4565b6127cb9190615a03565b6127d59082615b3c565b90505b91989197509095505050505050565b6127ef613850565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6017602052816000526040600020818154811061282d57600080fd5b600091825260209091206002909102018054600190910154909250905082565b600454600160a01b900460ff166128915760405162461bcd60e51b8152602060048201526008602482015267111254d05093115160c21b6044820152606401610f04565b60005487106128cb5760405162461bcd60e51b81526020600482015260066024820152650929cac9288b60d31b6044820152606401610f04565b600a8361ffff16101580156128ea5750600a5461ffff90811690841611155b61291f5760405162461bcd60e51b8152600401610f04906020808252600490820152634c45563160e01b604082015260600190565b61292a876000613e5f565b6129605760405162461bcd60e51b8152602060048201526007602482015266494e444f4f423160c81b6044820152606401610f04565b6001600160a01b038816158061298857506006546001600160a01b0389811661010090920416145b806129ab57506001600160a01b03881660009081526007602052604090205460ff165b6129e35760405162461bcd60e51b8152602060048201526009602482015268504f53544f4b454e3160b81b6044820152606401610f04565b6002546040516335313c2160e11b81523360048201526000916001600160a01b031690636a627842906024016020604051808303816000875af1158015612a2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a529190615c5c565b9050600080612a67338c898961ffff16613f05565b915091506000612a778b85614137565b90506000612a848c610f25565b9050612a928b828c8a614342565b600085815260156020526040902080546001600160a01b031916331790554260018301556002820184905560098201839055600a612ad461ffff8a16856159e4565b612ade9190615a03565b600a830155600b8201805462ffffff191688151562ffff0019161761010061ffff8b1602179055600c82018190556007820180546001600160a01b0319166001600160a01b038f16179055601880546000878152601960205260408120829055600182018355919091527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e01859055612b7b8583600a0154614400565b8515612b8b57612b8b8587613cef565b60408051828152602081018590528815158183015261ffff8a1660608201529051339187917f7851a428332e40237ac34a5efd508d9bbff0fb057da46bf99e1bd1b5c4adf6719181900360800190a350505050505050505050505050565b6060601a8054806020026020016040519081016040528092919081815260200182805480156120fe57602002820191906000526020600020905b815481526020019060010190808311612c23575050505050905090565b3360009081526005602052604090205460ff16612c8f5760405162461bcd60e51b815260206004820152600d60248201526c6f6e6c7920736574746c65727360981b6044820152606401610f04565b6000838152601460205260409020601081015460ff1615612cdb5760405162461bcd60e51b8152600401610f04906020808252600490820152635345543160e01b604082015260600190565b6000816008015411612d185760405162461bcd60e51b8152600401610f049060208082526004908201526329a2aa1960e11b604082015260600190565b60108101805460ff19166001179055600581018390556006810182905560078101546040805163313ce56760e01b815290516000926001600160a01b03169163313ce5679160048281019260209291908290030181865afa158015612d81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da59190615b8b565b612db090600a615b2d565b8385600660019054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e299190615b8b565b612e3490600a615b2d565b8560080154612e4391906159e4565b612e4d91906159e4565b612e579190615a03565b612e619190615a03565b600086815260166020526040902054600654919250612e929161010090046001600160a01b03908116911683613dfc565b6000858152601b6020526040812054601a8054919291612eb490600190615b3c565b81548110612ec457612ec461597e565b6000918252602080832090910154898352601b9091526040808320839055818352909120839055601a8054919250829184908110612f0457612f0461597e565b600091825260209091200155601a805480612f2157612f21615c99565b600190038181906000526020600020016000905590557f4c246f6c8d41233463bbb11c80907ea3f18c0b7c101910bfa5a599f65cacab4f87848888604051612f82949392919093845260208401929092526040830152606082015260800190565b60405180910390a150505050505050565b600081815260146020526040812054819067ffffffffffffffff811115612fbc57612fbc615669565b604051908082528060200260200182016040528015612fe5578160200160208202803683370190505b506000848152601460205260408120549192509067ffffffffffffffff81111561301157613011615669565b60405190808252806020026020018201604052801561303a578160200160208202803683370190505b50905060005b6000858152601460205260409020548110156131225760008581526014602052604090208054829081106130765761307661597e565b600091825260209091206003909102015483516001600160a01b03909116908490839081106130a7576130a761597e565b6001600160a01b0390921660209283029190910182015260008681526014909152604090208054829081106130de576130de61597e565b9060005260206000209060030201600001600101548282815181106131055761310561597e565b60209081029190910101528061311a81615a38565b915050613040565b5061312d82826134fb565b949350505050565b61313d613850565b601854156131785760405162461bcd60e51b81526020600482015260086024820152671350525390d3d31360c21b6044820152606401610f04565b600680546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6131a8613850565b6001600160a01b03821660009081526007602052604090205481151560ff9091161515036132075760405162461bcd60e51b815260206004820152600c60248201526b6368616e676520737461746560a01b6044820152606401610f04565b6001600160a01b0382166000908152600760205260409020805460ff1916821580159190911790915561329457600880546001600160a01b0384166000818152600960205260408120839055600183018455929092527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b03191690911790555050565b6001600160a01b03821660009081526009602052604081208054919055600880546132c190600190615b3c565b815481106132d1576132d161597e565b600091825260209091200154600880546001600160a01b0390921691839081106132fd576132fd61597e565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600880548061333c5761333c615c99565b600082815260209020810160001990810180546001600160a01b0319169055019055505b5050565b61336c613850565b6001600160a01b0381166133d15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610f04565b61206481613c9d565b6133e2613850565b600080546133f290600190615b3c565b815481106134025761340261597e565b9060005260206000209060070201600082815481106134235761342361597e565b600091825260209091206007909102018061343e8382615cfd565b5060018201548160010155600282015481600201556003820154816003015560048201548160040155600582015481600501556006820181600601908054613487929190614f9b565b50905050600080548061349c5761349c615c99565b600082815260208120600019909201916007830201906134bc8282615037565b600182016000905560028201600090556003820160009055600482016000905560058201600090556006820160006134f49190615071565b5050905550565b6000815183511461350b57600080fd5b6000805b845181101561114057600061353c86838151811061352f5761352f61597e565b6020026020010151611875565b92505050855160011461358657670de0b6b3a76400008583815181106135645761356461597e565b60200260200101518261357791906159e4565b6135819190615a03565b613588565b805b6135929084615a25565b92505080806135a090615a38565b91505061350f565b6135b0613850565b600082511180156135c2575080518251145b6135f95760405162461bcd60e51b815260206004820152600860248201526739b0b6b2903632b760c11b6044820152606401610f04565b600080546001810182559080526007027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56301806136368582615dda565b5060005b83518110156137fe5760008482815181106136575761365761597e565b60200260200101519050600061366c82611875565b92505050600081116136b05760405162461bcd60e51b815260206004820152600d60248201526c696e76616c69642070726f787960981b6044820152606401610f04565b85516001146136d8578483815181106136cb576136cb61597e565b60200260200101516136db565b60005b61ffff168460010160008282546136f29190615a25565b92505081905550836006016040518060600160405280846001600160a01b031681526020018786815181106137295761372961597e565b602002602001015161ffff168152602001885160011461378e57836137576002670de0b6b3a7640000615b2d565b8988815181106137695761376961597e565b602002602001015161ffff1661377f91906159e4565b6137899190615a03565b613791565b60005b90528154600181810184556000938452602093849020835160029093020180549484015161ffff16600160a01b026001600160b01b03199095166001600160a01b0390931692909217939093178155604090910151910155508190506137f681615a38565b91505061363a565b5050505050565b61380d613850565b60008086815481106138215761382161597e565b600091825260209091206007909102016002810195909555506003840192909255600483015560059091015550565b6001546001600160a01b03163314611eac5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f04565b600081116138e05760405162461bcd60e51b81526020600482015260036024820152620544f360ec1b6044820152606401610f04565b60008381526017602052604081208054849081106139005761390061597e565b906000526020600020906002020190506000816000015482600101541090508061392d5781548311613932565b815483105b6139645760405162461bcd60e51b8152602060048201526003602482015262544f3360e81b6044820152606401610f04565b50600101555050565b6002546040516331a9108f60e11b8152600481018490526000916001600160a01b031690636352211e90602401602060405180830381865afa1580156139b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139db9190615c14565b905081806139f15750336001600160a01b038216145b613a255760405162461bcd60e51b81526020600482015260056024820152644f574e4c5160d81b6044820152606401610f04565b60025460405163c3738f3f60e01b8152600481018590526001600160a01b039091169063c3738f3f90602401602060405180830381865afa158015613a6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a929190615e92565b613ac75760405162461bcd60e51b8152602060048201526006602482015265434c4f53453160d01b6044820152606401610f04565b613ad183826145e9565b613ada836146be565b613ae383614768565b613aec83614832565b600254604051630852cd8d60e31b8152600481018590526001600160a01b03909116906342966c6890602401600060405180830381600087803b158015613b3257600080fd5b505af1158015613b46573d6000803e3d6000fd5b505050600084815260166020908152604080832080546001600160a01b0319166001600160a01b0387169081179091556014835292819020600c810154600d820154600e830154600f9093015484519283529482015291820152606081019190915290915084907fad61fdefcf969920b58ee3fc753c769d85f23f36b446cf737c0c5e7dcf840a6e9060800160405180910390a3505050565b60008281526017602052604090208054613bfb90600190615b3c565b81548110613c0b57613c0b61597e565b9060005260206000209060020201601760008481526020019081526020016000208281548110613c3d57613c3d61597e565b6000918252602080832084546002909302019182556001938401549390910192909255838152601790915260409020805480613c7b57613c7b615c99565b6000828152602081206002600019909301928302018181556001015590555050565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008111613d255760405162461bcd60e51b81526020600482015260036024820152620544f360ec1b6044820152606401610f04565b600a546000838152601760205260409020546201000090910460ff1611613d745760405162461bcd60e51b8152602060048201526003602482015262544f3160e81b6044820152606401610f04565b6000613d7f83612f93565b9050818103613db65760405162461bcd60e51b81526020600482015260036024820152622a279960e91b6044820152606401610f04565b6000928352601760209081526040808520815180830190925292815280820193845282546001818101855593865291909420935160029091029093019283559051910155565b6040516001600160a01b03831660248201526044810182905261137d90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526148dd565b6000613efe8260008581548110613e7857613e7861597e565b90600052602060002090600702016002015460008681548110613e9d57613e9d61597e565b90600052602060002090600702016003015460008781548110613ec257613ec261597e565b90600052602060002090600702016004015460008881548110613ee757613ee761597e565b9060005260206000209060070201600501546149af565b9392505050565b60008080806001600160a01b038716613f715760003411613f505760405162461bcd60e51b8152602060048201526005602482015264434f4c4c3360d81b6044820152606401610f04565b349550613f5e888787614b1b565b9150613f6a8287615b3c565b905061412a565b6040516370a0823160e01b81526001600160a01b038981166004830152889188918316906370a0823190602401602060405180830381865afa158015613fbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fdf9190615c5c565b10156140165760405162461bcd60e51b8152600401610f049060208082526004908201526342414c3160e01b604082015260600190565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa15801561405d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140819190615c5c565b90506140986001600160a01b0383168b308b614b9b565b6040516370a0823160e01b815230600482015281906001600160a01b038416906370a0823190602401602060405180830381865afa1580156140de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141029190615c5c565b61410c9190615b3c565b97506141198a8989614b1b565b93506141258489615b3c565b925050505b9097909650945050505050565b6000818152601460205260408120815b6000858154811061415a5761415a61597e565b906000526020600020906007020160060180549050811015611140576000806141b16000888154811061418f5761418f61597e565b906000526020600020906007020160060184815481106112c3576112c361597e565b5091509150836000016040518060a0016040528060008a815481106141d8576141d861597e565b906000526020600020906007020160060186815481106141fa576141fa61597e565b600091825260208083206040805160608082018352600295860290930180546001600160a01b03808216845261ffff600160a01b9283900481168589015260019384015485870152938a529c8316898701526001600160501b039b8c168985015288850188905260809889018890528a548083018c559a885296859020895180516003909c0290910180548288015185169099026001600160b01b03199099169b909d169a909a17969096178b5597810151948a019490945590850151979091018054928501519185015194909301518616600160701b0269ffffffffffffffffffff60701b19948616600160601b02949094166bffffffffffffffffffffffff60601b199190961662010000026bffffffffffffffffffffffff1990921696909416959095179490941791909116919091171790558061433a81615a38565b915050614147565b600081801561435057508484115b156143665761435f8585615b3c565b9050614385565b8115801561437357508385115b15614385576143828486615b3c565b90505b80156137fe576103e86143a0670de0b6b3a7640000856159e4565b6143aa9190615a03565b856143bd670de0b6b3a7640000846159e4565b6143c79190615a03565b11156137fe5760405162461bcd60e51b8152602060048201526008602482015267534c49505041474560c01b6044820152606401610f04565b6000828152601460205260409020600b015460ff161561445c576000828152601460209081526040808320600701546001600160a01b03168352601190915281208054839290614451908490615a25565b909155506144999050565b6000828152601460209081526040808320600701546001600160a01b03168352601290915281208054839290614493908490615a25565b90915550505b6000828152601460209081526040808320600701546001600160a01b03168352601390915290205415613360576000828152601460209081526040808320600701546001600160a01b03168352601282528083205460119092528220541161453b576000838152601460209081526040808320600701546001600160a01b0316835260118252808320546012909252909120546145369190615b3c565b614576565b6000838152601460209081526040808320600701546001600160a01b0316835260128252808320546011909252909120546145769190615b3c565b6000848152601460209081526040808320600701546001600160a01b03168352601390915290205490915081111561137d5760405162461bcd60e51b81526020600482015260166024820152751b585e0818dbdb1b185d195c985b081c995858da195960521b6044820152606401610f04565b6000828152601460205260408120908061460285612670565b909250905060006146138284615a25565b905060008060008060006146268b611382565b94509450945094509450838611614646576146418685615b3c565b614649565b60005b93506146568b8b86614bd3565b4260038a015560048901869055600d89018590558180156146745750805b61467f576000614681565b825b600e8a0155816146a6578860090154831161469c57826146a9565b88600901546146a9565b60005b89600f01819055505050505050505050505050565b600081815260196020526040812054601880549192916146e090600190615b3c565b815481106146f0576146f061597e565b600091825260208083209091015485835260199091526040808320839055818352909120839055601880549192508291849081106147305761473061597e565b600091825260209091200155601880548061474d5761474d615c99565b60019003818190600052602060002001600090559055505050565b60005b6000828152601460205260409020548110156133605760008281526014602052604081208054839081106147a1576147a161597e565b600091825260208220600390910201805490925081906147c9906001600160a01b0316611875565b50600290940180546001600160501b03909516600160701b0269ffffffffffffffffffff60701b1961ffff909316600160601b02929092166bffffffffffffffffffffffff60601b1990951694909417179092555081905061482a81615a38565b91505061476b565b6000818152601460205260409020600b015460ff1615614896576000818152601460209081526040808320600a8101546007909101546001600160a01b031684526011909252822080549192909161488b908490615b3c565b909155506120649050565b6000818152601460209081526040808320600a8101546007909101546001600160a01b03168452601290925282208054919290916148d5908490615b3c565b909155505050565b6000614932826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614e879092919063ffffffff16565b80519091501561137d57808060200190518101906149509190615e92565b61137d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610f04565b600085156149bd57856149bf565b425b9550600185101580156149d3575060018410155b15614a68576004805460405163045f145760e31b81529182018890526000916001600160a01b03909116906322f8a2b890602401602060405180830381865afa158015614a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a489190615c5c565b905085811080614a5757508481115b15614a66576000915050614b12565b505b600183101580614a79575060018210155b15614b0e5760048054604051631f11cf0d60e11b81529182018890526000916001600160a01b0390911690633e239e1a90602401602060405180830381865afa158015614aca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614aee9190615c5c565b905083811080614afd57508281115b15614b0c576000915050614b12565b505b5060015b95945050505050565b600080600a614b2a84866159e4565b614b349190615a03565b90506000620186a0600d5483614b4a91906159e4565b614b549190615a03565b9050600080614b6288612536565b90925090508115614b8f5780614b7883856159e4565b614b829190615a03565b614b8c9084615b3c565b92505b50909695505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526118499085906323b872dd60e01b90608401613e28565b60008381526014602052604090208115614e725760065460078201546001600160a01b036101009092048216911603614c335760108101805460ff191660011790556007810154614c2e906001600160a01b03168484613dfc565b611849565b8060090154821115614d9b5760078101546001600160a01b0316614cf457600981015460405147916001600160a01b03861691600081818185875af1925050503d8060008114614c9f576040519150601f19603f3d011682016040523d82523d6000602084013e614ca4565b606091505b5050506009820154614cb69082615b3c565b471015614cee5760405162461bcd60e51b8152600401610f04906020808252600490820152634e41543160e01b604082015260600190565b50614d15565b60098101546007820154614d15916001600160a01b03909116908590613dfc565b6009810154614d249083615b3c565b6008820155601a80546000868152601b60205260408082208390556001830184559281527f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e909101869055905185917f1cf3a4d81180ed8c843ad38f7adadb6357459df6a134d14614cf7ca32dbee42191a2611849565b60108101805460ff1916600117905560078101546001600160a01b0316614e595760405147906001600160a01b038516908490600081818185875af1925050503d8060008114614e07576040519150601f19603f3d011682016040523d82523d6000602084013e614e0c565b606091505b5050508281614e1b9190615b3c565b471015614e535760405162461bcd60e51b8152600401610f04906020808252600490820152634e41543160e01b604082015260600190565b50611849565b6007810154614c2e906001600160a01b03168484613dfc565b60108101805460ff1916600117905550505050565b606061312d8484600085856001600160a01b0385163b614ee95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610f04565b600080866001600160a01b03168587604051614f059190615eaf565b60006040518083038185875af1925050503d8060008114614f42576040519150601f19603f3d011682016040523d82523d6000602084013e614f47565b606091505b5091509150614f57828286614f62565b979650505050505050565b60608315614f71575081613efe565b825115614f815782518084602001fd5b8160405162461bcd60e51b8152600401610f049190615ecb565b8280548282559060005260206000209060020281019282156150275760005260206000209160020282015b8281111561502757825482546001600160a01b039091166001600160a01b031982168117845584546001600160b01b031990921617600160a01b9182900461ffff169091021782556001808401549083015560029283019290910190614fc6565b5061503392915061508e565b5090565b50805461504390615994565b6000825580601f10615053575050565b601f01602090049060005260206000209081019061206491906150b4565b508054600082556002029060005260206000209081019061206491905b5b808211156150335780546001600160b01b03191681556000600182015560020161508f565b5b8082111561503357600081556001016150b5565b61ffff8116811461206457600080fd5b6000602082840312156150eb57600080fd5b8135613efe816150c9565b60006020828403121561510857600080fd5b5035919050565b6001600160a01b038116811461206457600080fd5b60006020828403121561513657600080fd5b8135613efe8161510f565b602080825282518282018190526000919060409081850190868401855b828110156151835781518051855286015186850152928401929085019060010161515e565b5091979650505050505050565b60ff8116811461206457600080fd5b6000602082840312156151b157600080fd5b8135613efe81615190565b600080602083850312156151cf57600080fd5b823567ffffffffffffffff808211156151e757600080fd5b818501915085601f8301126151fb57600080fd5b81358181111561520a57600080fd5b86602082850101111561521c57600080fd5b60209290920196919550909350505050565b60008060006060848603121561524357600080fd5b505081359360208301359350604090920135919050565b6000806040838503121561526d57600080fd5b50508035926020909101359150565b60005b8381101561529757818101518382015260200161527f565b50506000910152565b600081518084526152b881602086016020860161527c565b601f01601f19169290920160200192915050565b821515815260406020820152600061312d60408301846152a0565b801515811461206457600080fd5b6000806040838503121561530857600080fd5b82356153138161510f565b91506020830135615323816152e7565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015614b8f5783516001600160a01b03168352928401929184019160010161534a565b60c08152600061538260c08301896152a0565b60208301979097525060408101949094526060840192909252608083015260a090910152919050565b6000610220820190508d51825260208e0151602083015260408e0151604083015260608e0151606083015260808e0151608083015260a08e015160a08301526153ff60c083018e6001600160a01b03169052565b8b60e08301528a6101008301528961012083015261542261014083018a15159052565b61ffff881661016083015286610180830152856101a0830152846101c0830152836101e083015261545861020083018415159052565b9d9c50505050505050505050505050565b6000806040838503121561547c57600080fd5b82356154878161510f565b946020939093013593505050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b8481101561558957603f198a8503018652825160e081518187526154e3828801826152a0565b838c0151888d01528a8401518b890152606080850151818a0152608080860151908a015260a080860151908a015260c094850151898303958a01959095528451808352948d0194879450909250908c01905b8084101561557357845180516001600160a01b031683528d81015161ffff168e8401528c01518c830152938c01936001939093019290820190615535565b50988b01989650505092880192506001016154bd565b50919998505050505050505050565b6000602082840312156155aa57600080fd5b8135613efe816152e7565b600080600080600080600080610100898b0312156155d257600080fd5b88356155dd8161510f565b97506020890135965060408901359550606089013594506080890135935060a0890135615609816150c9565b925060c0890135615619816152e7565b8092505060e089013590509295985092959890939650565b6020808252825182820181905260009190848201906040850190845b81811015614b8f5783518352928401929184019160010161564d565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156156a8576156a8615669565b604052919050565b600067ffffffffffffffff8211156156ca576156ca615669565b5060051b60200190565b600082601f8301126156e557600080fd5b813560206156fa6156f5836156b0565b61567f565b82815260059290921b8401810191818101908684111561571957600080fd5b8286015b8481101561573d5780356157308161510f565b835291830191830161571d565b509695505050505050565b6000806040838503121561575b57600080fd5b823567ffffffffffffffff8082111561577357600080fd5b61577f868387016156d4565b935060209150818501358181111561579657600080fd5b85019050601f810186136157a957600080fd5b80356157b76156f5826156b0565b81815260059190911b820183019083810190888311156157d657600080fd5b928401925b828410156157f4578335825292840192908401906157db565b80955050505050509250929050565b600082601f83011261581457600080fd5b813560206158246156f5836156b0565b82815260059290921b8401810191818101908684111561584357600080fd5b8286015b8481101561573d57803561585a816150c9565b8352918301918301615847565b60008060006060848603121561587c57600080fd5b833567ffffffffffffffff8082111561589457600080fd5b818601915086601f8301126158a857600080fd5b81356020828211156158bc576158bc615669565b6158ce601f8301601f1916820161567f565b82815289828487010111156158e257600080fd5b8282860183830137600092810182019290925290955086013591508082111561590a57600080fd5b615916878388016156d4565b9350604086013591508082111561592c57600080fd5b5061593986828701615803565b9150509250925092565b600080600080600060a0868803121561595b57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806159a857607f821691505b6020821081036159c857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156159fe576159fe6159ce565b500290565b600082615a2057634e487b7160e01b600052601260045260246000fd5b500490565b808201808211156120a0576120a06159ce565b600060018201615a4a57615a4a6159ce565b5060010190565b600181815b80851115611e92578160001904821115615a7257615a726159ce565b80851615615a7f57918102915b93841c9390800290615a56565b600082615a9b575060016120a0565b81615aa8575060006120a0565b8160018114615abe5760028114615ac857615ae4565b60019150506120a0565b60ff841115615ad957615ad96159ce565b50506001821b6120a0565b5060208310610133831016604e8410600b8410161715615b07575081810a6120a0565b615b118383615a51565b8060001904821115615b2557615b256159ce565b029392505050565b6000613efe60ff841683615a8c565b818103818111156120a0576120a06159ce565b600060ff821660ff8103615b6557615b656159ce565b60010192915050565b600060208284031215615b8057600080fd5b8151613efe816150c9565b600060208284031215615b9d57600080fd5b8151613efe81615190565b80516001600160501b0381168114615bbf57600080fd5b919050565b600080600080600060a08688031215615bdc57600080fd5b615be586615ba8565b9450602086015193506040860151925060608601519150615c0860808701615ba8565b90509295509295909350565b600060208284031215615c2657600080fd5b8151613efe8161510f565b60208082526011908201527036bab9ba1037bbb7103837b9b4ba34b7b760791b604082015260600190565b600060208284031215615c6e57600080fd5b5051919050565b60008060408385031215615c8857600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603160045260246000fd5b601f82111561137d57600081815260208120601f850160051c81016020861015615cd65750805b601f850160051c820191505b81811015615cf557828155600101615ce2565b505050505050565b818103615d08575050565b615d128254615994565b67ffffffffffffffff811115615d2a57615d2a615669565b615d3e81615d388454615994565b84615caf565b6000601f821160018114615d725760008315615d5a5750848201545b600019600385901b1c1916600184901b1784556137fe565b600085815260209020601f19841690600086815260209020845b83811015615dac5782860154825560019586019590910190602001615d8c565b5085831015615dca5781850154600019600388901b60f8161c191681555b5050505050600190811b01905550565b815167ffffffffffffffff811115615df457615df4615669565b615e0281615d388454615994565b602080601f831160018114615e375760008415615e1f5750858301515b600019600386901b1c1916600185901b178555615cf5565b600085815260208120601f198616915b82811015615e6657888601518255948401946001909101908401615e47565b5085821015615dca57939096015160001960f8600387901b161c19169092555050600190811b01905550565b600060208284031215615ea457600080fd5b8151613efe816152e7565b60008251615ec181846020870161527c565b9190910192915050565b602081526000613efe60208301846152a056fea164736f6c6343000810000a60806040526032600f553480156200001657600080fd5b50604051620026c1380380620026c1833981016040819052620000399162000154565b60408051808201825260208082527f5969656c64696669636174696f6e2050657270657475616c2046757475726573818301528251808401909352600583526438332ca22360d91b90830152906000620000948382620002b8565b506001620000a38282620002b8565b505050620000c0620000ba620000e860201b60201c565b620000ec565b600d620000ce8282620002b8565b5050600b80546001600160a01b0319163317905562000384565b3390565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b634e487b7160e01b600052604160045260246000fd5b600060208083850312156200016857600080fd5b82516001600160401b03808211156200018057600080fd5b818501915085601f8301126200019557600080fd5b815181811115620001aa57620001aa6200013e565b604051601f8201601f19908116603f01168101908382118183101715620001d557620001d56200013e565b816040528281528886848701011115620001ee57600080fd5b600093505b82841015620002125784840186015181850187015292850192620001f3565b600086848301015280965050505050505092915050565b600181811c908216806200023e57607f821691505b6020821081036200025f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002b357600081815260208120601f850160051c810160208610156200028e5750805b601f850160051c820191505b81811015620002af578281556001016200029a565b5050505b505050565b81516001600160401b03811115620002d457620002d46200013e565b620002ec81620002e5845462000229565b8462000265565b602080601f8311600181146200032457600084156200030b5750858301515b600019600386901b1c1916600185901b178555620002af565b600085815260208120601f198616915b82811015620003555788860151825594840194600190910190840162000334565b5085821015620003745787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61232d80620003946000396000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c80636a62784211610125578063afd50d8f116100ad578063c87b56dd1161007c578063c87b56dd146104c1578063e8a3d485146104d4578063e985e9c5146104dc578063f2fde38b14610518578063ffa801361461052b57600080fd5b8063afd50d8f14610468578063b6b8194014610488578063b88d4fde1461049b578063c3738f3f146104ae57600080fd5b80637974e46a116100f45780637974e46a146104215780638da5cb5b1461042957806395d89b411461043a578063a22cb46514610442578063ad2f852a1461045557600080fd5b80636a627842146103d357806370a08231146103e6578063715018a6146103f957806376772cf81461040157600080fd5b8063274de61e116101a857806342842e0e1161017757806342842e0e1461037457806342966c68146103875780634f6ccce71461039a57806355f804b3146103ad5780636352211e146103c057600080fd5b8063274de61e146102fc5780632a55205a1461031c5780632d88931b1461034e5780632f745c591461036157600080fd5b8063095ea7b3116101ef578063095ea7b31461029e57806310bd14fe146102b157806318160ddd146102c457806320e3fa50146102d657806323b872dd146102e957600080fd5b806301ffc9a71461022157806306d254da1461024957806306fdde031461025e578063081812fc14610273575b600080fd5b61023461022f366004611c16565b61054b565b60405190151581526020015b60405180910390f35b61025c610257366004611c51565b61055c565b005b6102666105ae565b6040516102409190611cbc565b610286610281366004611ccf565b610640565b6040516001600160a01b039091168152602001610240565b61025c6102ac366004611ce8565b610667565b600b54610286906001600160a01b031681565b6008545b604051908152602001610240565b6102c86102e4366004611ce8565b610781565b61025c6102f7366004611d12565b6107b2565b6102c861030a366004611ccf565b60116020526000908152604090205481565b61032f61032a366004611d4e565b6107e3565b604080516001600160a01b039093168352602083019190915201610240565b61025c61035c366004611c51565b61081d565b6102c861036f366004611ce8565b610847565b61025c610382366004611d12565b6108dd565b61025c610395366004611ccf565b6108f8565b6102c86103a8366004611ccf565b6109b1565b61025c6103bb366004611dfc565b610a44565b6102866103ce366004611ccf565b610a9a565b6102c86103e1366004611c51565b610afa565b6102c86103f4366004611c51565b610bcc565b61025c610c52565b6102c861040f366004611ccf565b60126020526000908152604090205481565b6102c8610c66565b600a546001600160a01b0316610286565b610266610c76565b61025c610450366004611e45565b610c85565b600e54610286906001600160a01b031681565b6102c8610476366004611ccf565b60136020526000908152604090205481565b61025c610496366004611ccf565b610c94565b61025c6104a9366004611e81565b610ccf565b6102346104bc366004611ccf565b610d07565b6102666104cf366004611ccf565b610d26565b610266610d82565b6102346104ea366004611efd565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b61025c610526366004611c51565b610db0565b61053e610539366004611c51565b610e29565b6040516102409190611f30565b600061055682610e95565b92915050565b610564610eba565b600e80546001600160a01b0319166001600160a01b0383169081179091556040517f0f2a87e68f9d4311c1d18e960f7873198e70403a037237cdd2c583c69cdddf1f90600090a250565b6060600080546105bd90611f74565b80601f01602080910402602001604051908101604052809291908181526020018280546105e990611f74565b80156106365780601f1061060b57610100808354040283529160200191610636565b820191906000526020600020905b81548152906001019060200180831161061957829003601f168201915b5050505050905090565b600061064b82610f14565b506000908152600460205260409020546001600160a01b031690565b600061067282610a9a565b9050806001600160a01b0316836001600160a01b0316036106e45760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610700575061070081336104ea565b6107725760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c000060648201526084016106db565b61077c8383610f73565b505050565b6010602052816000526040600020818154811061079d57600080fd5b90600052602060002001600091509150505481565b6107bc3382610fe1565b6107d85760405162461bcd60e51b81526004016106db90611fae565b61077c838383611060565b600e54600f5460009182916001600160a01b03909116906103e8906108089086612012565b6108129190612047565b915091509250929050565b610825610eba565b600b80546001600160a01b0319166001600160a01b0392909216919091179055565b600061085283610bcc565b82106108b45760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b60648201526084016106db565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b61077c83838360405180602001604052806000815250610ccf565b600b546001600160a01b0316331461093f5760405162461bcd60e51b815260206004820152600a6024820152696f6e6c7920706572707360b01b60448201526064016106db565b600061094a82610a9a565b6000838152600260205260409020549091506001600160a01b031661096e57600080fd5b6109778261120d565b6040516001600160a01b0382169083907ff6554c3a5d28e08c120b5a69c7edbaf52f935bd2596a60b8a18e282cd257cddb90600090a35050565b60006109bc60085490565b8210610a1f5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b60648201526084016106db565b60088281548110610a3257610a3261205b565b90600052602060002001549050919050565b610a4c610eba565b600d610a5882826120bf565b5080604051610a67919061217f565b604051908190038120907f199e933997358e1789d8b56ea8c551befeb05ce2fe3fe506199f1230f5a591b490600090a250565b6000818152600260205260408120546001600160a01b0316806105565760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016106db565b600b546000906001600160a01b03163314610b445760405162461bcd60e51b815260206004820152600a6024820152696f6e6c7920706572707360b01b60448201526064016106db565b610b52600c80546001019055565b610b6482610b5f600c5490565b6112bc565b4260126000610b72600c5490565b81526020810191909152604001600020556001600160a01b038216610b96600c5490565b6040517ff3cea5493d790af0133817606f7350a91d7f154ea52eaa79d179d4d231e5010290600090a3600c54610556565b919050565b60006001600160a01b038216610c365760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b60648201526084016106db565b506001600160a01b031660009081526003602052604090205490565b610c5a610eba565b610c6460006112d6565b565b6000610c71600c5490565b905090565b6060600180546105bd90611f74565b610c90338383611328565b5050565b610c9c610eba565b600f81905560405181907f2ad2ae73af42f598ecb723109218def6abfe2e801eb5719ab4acbf9adc91c65d90600090a250565b610cd93383610fe1565b610cf55760405162461bcd60e51b81526004016106db90611fae565b610d01848484846113f6565b50505050565b6000818152600260205260408120546001600160a01b03161515610556565b6000818152600260205260409020546060906001600160a01b0316610d4a57600080fd5b610d52611429565b610d5b83611438565b604051602001610d6c92919061219b565b6040516020818303038152906040529050919050565b6060610d8c611429565b604051602001610d9c91906121da565b604051602081830303815290604052905090565b610db8610eba565b6001600160a01b038116610e1d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106db565b610e26816112d6565b50565b6001600160a01b038116600090815260106020908152604091829020805483518184028101840190945280845260609392830182828015610e8957602002820191906000526020600020905b815481526020019060010190808311610e75575b50505050509050919050565b60006001600160e01b0319821663780e9d6360e01b1480610556575061055682611539565b600a546001600160a01b03163314610c645760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106db565b6000818152600260205260409020546001600160a01b0316610e265760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016106db565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610fa882610a9a565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080610fed83610a9a565b9050806001600160a01b0316846001600160a01b0316148061103457506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b806110585750836001600160a01b031661104d84610640565b6001600160a01b0316145b949350505050565b826001600160a01b031661107382610a9a565b6001600160a01b0316146110d75760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b60648201526084016106db565b6001600160a01b0382166111395760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016106db565b611144838383611589565b61114f600082610f73565b6001600160a01b038316600090815260036020526040812080546001929061117890849061220b565b90915550506001600160a01b03821660009081526003602052604081208054600192906111a690849061221e565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a461077c8383836115a5565b600061121882610a9a565b905061122681600084611589565b611231600083610f73565b6001600160a01b038116600090815260036020526040812080546001929061125a90849061220b565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a4610c90816000846115a5565b610c9082826040518060200160405280600081525061172e565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b816001600160a01b0316836001600160a01b0316036113895760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016106db565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b611401848484611060565b61140d84848484611761565b610d015760405162461bcd60e51b81526004016106db90612231565b6060600d80546105bd90611f74565b60608160000361145f5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611489578061147381612283565b91506114829050600a83612047565b9150611463565b60008167ffffffffffffffff8111156114a4576114a4611d70565b6040519080825280601f01601f1916602001820160405280156114ce576020820181803683370190505b5090505b8415611058576114e360018361220b565b91506114f0600a8661229c565b6114fb90603061221e565b60f81b8183815181106115105761151061205b565b60200101906001600160f81b031916908160001a905350611532600a86612047565b94506114d2565b60006001600160e01b031982166380ac58cd60e01b148061156a57506001600160e01b03198216635b5e139f60e01b145b8061055657506301ffc9a760e01b6001600160e01b0319831614610556565b600081815260136020526040902042905561077c838383611862565b6001600160a01b038316156116df576000818152601160209081526040808320546001600160a01b03871684526010909252822080549192916115ea9060019061220b565b815481106115fa576115fa61205b565b60009182526020808320909101546001600160a01b0388168352601090915260409091208054919250906116309060019061220b565b815481106116405761164061205b565b906000526020600020015460106000876001600160a01b03166001600160a01b0316815260200190815260200160002083815481106116815761168161205b565b60009182526020808320909101929092556001600160a01b03871681526010909152604090208054806116b6576116b66122b0565b600082815260208082208301600019908101839055909201909255918152601190915260409020555b6001600160a01b0382161561077c576001600160a01b03919091166000908152601060208181526040808420805486865260118452918520829055928252600181018355918352909120015550565b611738838361191a565b6117456000848484611761565b61077c5760405162461bcd60e51b81526004016106db90612231565b60006001600160a01b0384163b1561185757604051630a85bd0160e11b81526001600160a01b0385169063150b7a02906117a59033908990889088906004016122c6565b6020604051808303816000875af19250505080156117e0575060408051601f3d908101601f191682019092526117dd91810190612303565b60015b61183d573d80801561180e576040519150601f19603f3d011682016040523d82523d6000602084013e611813565b606091505b5080516000036118355760405162461bcd60e51b81526004016106db90612231565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611058565b506001949350505050565b6001600160a01b0383166118bd576118b881600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6118e0565b816001600160a01b0316836001600160a01b0316146118e0576118e08382611a70565b6001600160a01b0382166118f75761077c81611b0d565b826001600160a01b0316826001600160a01b03161461077c5761077c8282611bbc565b6001600160a01b0382166119705760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016106db565b6000818152600260205260409020546001600160a01b0316156119d55760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016106db565b6119e160008383611589565b6001600160a01b0382166000908152600360205260408120805460019290611a0a90849061221e565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4610c90600083836115a5565b60006001611a7d84610bcc565b611a87919061220b565b600083815260076020526040902054909150808214611ada576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090611b1f9060019061220b565b60008381526009602052604081205460088054939450909284908110611b4757611b4761205b565b906000526020600020015490508060088381548110611b6857611b6861205b565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480611ba057611ba06122b0565b6001900381819060005260206000200160009055905550505050565b6000611bc783610bcc565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6001600160e01b031981168114610e2657600080fd5b600060208284031215611c2857600080fd5b8135611c3381611c00565b9392505050565b80356001600160a01b0381168114610bc757600080fd5b600060208284031215611c6357600080fd5b611c3382611c3a565b60005b83811015611c87578181015183820152602001611c6f565b50506000910152565b60008151808452611ca8816020860160208601611c6c565b601f01601f19169290920160200192915050565b602081526000611c336020830184611c90565b600060208284031215611ce157600080fd5b5035919050565b60008060408385031215611cfb57600080fd5b611d0483611c3a565b946020939093013593505050565b600080600060608486031215611d2757600080fd5b611d3084611c3a565b9250611d3e60208501611c3a565b9150604084013590509250925092565b60008060408385031215611d6157600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff80841115611da157611da1611d70565b604051601f8501601f19908116603f01168101908282118183101715611dc957611dc9611d70565b81604052809350858152868686011115611de257600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215611e0e57600080fd5b813567ffffffffffffffff811115611e2557600080fd5b8201601f81018413611e3657600080fd5b61105884823560208401611d86565b60008060408385031215611e5857600080fd5b611e6183611c3a565b915060208301358015158114611e7657600080fd5b809150509250929050565b60008060008060808587031215611e9757600080fd5b611ea085611c3a565b9350611eae60208601611c3a565b925060408501359150606085013567ffffffffffffffff811115611ed157600080fd5b8501601f81018713611ee257600080fd5b611ef187823560208401611d86565b91505092959194509250565b60008060408385031215611f1057600080fd5b611f1983611c3a565b9150611f2760208401611c3a565b90509250929050565b6020808252825182820181905260009190848201906040850190845b81811015611f6857835183529284019291840191600101611f4c565b50909695505050505050565b600181811c90821680611f8857607f821691505b602082108103611fa857634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561202c5761202c611ffc565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261205657612056612031565b500490565b634e487b7160e01b600052603260045260246000fd5b601f82111561077c57600081815260208120601f850160051c810160208610156120985750805b601f850160051c820191505b818110156120b7578281556001016120a4565b505050505050565b815167ffffffffffffffff8111156120d9576120d9611d70565b6120ed816120e78454611f74565b84612071565b602080601f831160018114612122576000841561210a5750858301515b600019600386901b1c1916600185901b1785556120b7565b600085815260208120601f198616915b8281101561215157888601518255948401946001909101908401612132565b508582101561216f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008251612191818460208701611c6c565b9190910192915050565b600083516121ad818460208801611c6c565b8351908301906121c1818360208801611c6c565b64173539b7b760d91b9101908152600501949350505050565b600082516121ec818460208701611c6c565b6c31b7b73a3930b1ba173539b7b760991b920191825250600d01919050565b8181038181111561055657610556611ffc565b8082018082111561055657610556611ffc565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60006001820161229557612295611ffc565b5060010190565b6000826122ab576122ab612031565b500690565b634e487b7160e01b600052603160045260246000fd5b6001600160a01b03858116825284166020820152604081018390526080606082018190526000906122f990830184611c90565b9695505050505050565b60006020828403121561231557600080fd5b8151611c3381611c0056fea164736f6c6343000810000a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003768747470733a2f2f6170692e7969656c64696669636174696f6e2e636f6d2f70667964662f617262697472756d2f6d657461646174612f000000000000000000
Deployed Bytecode
0x6080604052600436106104105760003560e01c80638da5cb5b1161021e578063cb03890711610123578063e03527d5116100ab578063f2fde38b1161007a578063f2fde38b14610e1f578063f53d9ec114610e3f578063f707159714610e5f578063fd5891c414610e7f578063fffa41b114610e9f57600080fd5b8063e03527d514610d9f578063e34274ef14610dbf578063e867d90414610ddf578063ee9b802714610dff57600080fd5b8063d5e34836116100f2578063d5e3483614610d0a578063d834123e14610d2a578063dc73131814610d4a578063dcb03dc614610d6a578063df72ad2714610d7d57600080fd5b8063cb03890714610c9e578063d14d40bb14610cbe578063d19529ff14610cd4578063d2c76d7414610cea57600080fd5b8063ae3302c2116101a6578063b91d08ce11610175578063b91d08ce14610bfa578063ba93fd9014610c1a578063bd4bf07a14610c30578063c2e5ec0414610c4e578063c70a900f14610c6e57600080fd5b8063ae3302c214610b61578063b54710e714610b8f578063b7fa7cfc14610baf578063b81bb71014610be457600080fd5b806396e61bc7116101ed57806396e61bc7146109e357806399fbab8814610a19578063a126d60114610aff578063a1db978214610b1f578063a2f0a1f214610b3f57600080fd5b80638da5cb5b146109515780638f0525ec1461096f57806391bb214b1461098f57806392f8eb94146109b157600080fd5b8063594a60ae116103245780636c9963f4116102ac5780637c011be81161027b5780637c011be8146108a95780637f3b7a02146108c957806384a43170146108df578063861d1dfa146108ff57806389701db51461093157600080fd5b80636c9963f4146108265780636e04ff0d14610846578063715018a61461087457806377a354651461088957600080fd5b806362c7536d116102f357806362c7536d1461076c57806365f290f714610799578063667073fc146107c657806366c62643146107e65780636b4b68661461080657600080fd5b8063594a60ae146106ec5780635ad15eda1461070c5780635ba873101461072c5780635bc412d91461074c57600080fd5b806339d99cca116103a757806348bb4e331161037657806348bb4e33146106285780634ada218b146106485780634dfdeee5146106695780634f8f53321461067f57806358920140146106a457600080fd5b806339d99cca146105925780633a2baafd146105b25780633f08e526146105e85780634585e33b1461060857600080fd5b8063182d8747116103e3578063182d8747146104c95780631a090154146104f95780631a79344c14610519578063335db3061461056557600080fd5b80630679d362146104155780630f1627931461043757806310edc9801461046a578063174b63991461049c575b600080fd5b34801561042157600080fd5b506104356104303660046150d9565b610ebf565b005b34801561044357600080fd5b506104576104523660046150f6565b610f25565b6040519081526020015b60405180910390f35b34801561047657600080fd5b506002546001600160a01b03165b6040516001600160a01b039091168152602001610461565b3480156104a857600080fd5b506104576104b7366004615124565b60136020526000908152604090205481565b3480156104d557600080fd5b506104e96104e43660046150f6565b611148565b6040519015158152602001610461565b34801561050557600080fd5b506104356105143660046150f6565b61122f565b34801561052557600080fd5b506105396105343660046150f6565b611382565b60408051958652602086019490945292840191909152151560608301521515608082015260a001610461565b34801561057157600080fd5b506105856105803660046150f6565b6116a3565b6040516104619190615141565b34801561059e57600080fd5b506104356105ad36600461519f565b611729565b3480156105be57600080fd5b506104846105cd3660046150f6565b6015602052600090815260409020546001600160a01b031681565b3480156105f457600080fd5b506104356106033660046150f6565b611782565b34801561061457600080fd5b506104356106233660046151bc565b6117cb565b34801561063457600080fd5b5061043561064336600461519f565b61184f565b34801561065457600080fd5b506004546104e990600160a01b900460ff1681565b34801561067557600080fd5b50610457600c5481565b34801561068b57600080fd5b506006546104849061010090046001600160a01b031681565b3480156106b057600080fd5b506106c46106bf366004615124565b611875565b6040805161ffff90941684526001600160501b03909216602084015290820152606001610461565b3480156106f857600080fd5b5061043561070736600461522e565b6119f3565b34801561071857600080fd5b506104e96107273660046150f6565b611a9b565b34801561073857600080fd5b506104576107473660046150f6565b611b8c565b34801561075857600080fd5b506104356107673660046150f6565b611bad565b34801561077857600080fd5b50610457610787366004615124565b60126020526000908152604090205481565b3480156107a557600080fd5b506104576107b4366004615124565b60116020526000908152604090205481565b3480156107d257600080fd5b506104e96107e13660046150f6565b611c0b565b3480156107f257600080fd5b506104356108013660046150f6565b611cc1565b34801561081257600080fd5b5061043561082136600461525a565b611d1f565b34801561083257600080fd5b506104356108413660046150f6565b611dc6565b34801561085257600080fd5b506108666108613660046151bc565b611e25565b6040516104619291906152cc565b34801561088057600080fd5b50610435611e9a565b34801561089557600080fd5b506104356108a43660046152f5565b611eae565b3480156108b557600080fd5b506104356108c436600461525a565b611f3a565b3480156108d557600080fd5b50610457600e5481565b3480156108eb57600080fd5b506104356108fa3660046150f6565b611fe1565b34801561090b57600080fd5b50600a5461091f9062010000900460ff1681565b60405160ff9091168152602001610461565b34801561093d57600080fd5b5061043561094c3660046150f6565b612040565b34801561095d57600080fd5b506001546001600160a01b0316610484565b34801561097b57600080fd5b5061045761098a3660046150f6565b612067565b34801561099b57600080fd5b506109a46120a6565b604051610461919061532e565b3480156109bd57600080fd5b506109d16109cc3660046150f6565b612108565b6040516104619695949392919061536f565b3480156109ef57600080fd5b506104846109fe3660046150f6565b6016602052600090815260409020546001600160a01b031681565b348015610a2557600080fd5b50610ae7610a343660046150f6565b601460209081526000918252604091829020825160c081018452600182015481526002820154928101929092526003810154928201929092526004820154606082015260058201546080820152600682015460a0820152600782015460088301546009840154600a850154600b860154600c870154600d880154600e890154600f8a01546010909a015498996001600160a01b039098169896979596949560ff8086169661010090960461ffff1695168c565b6040516104619c9b9a999897969594939291906153ab565b348015610b0b57600080fd5b50610435610b1a3660046150f6565b6121dc565b348015610b2b57600080fd5b50610435610b3a366004615469565b6121e7565b348015610b4b57600080fd5b50610b54612299565b6040516104619190615495565b348015610b6d57600080fd5b50600a54610b7c9061ffff1681565b60405161ffff9091168152602001610461565b348015610b9b57600080fd5b506109a4610baa3660046150f6565b612444565b348015610bbb57600080fd5b50610bcf610bca366004615124565b612536565b60408051928352602083019190915201610461565b348015610bf057600080fd5b50610457600f5481565b348015610c0657600080fd5b50610457610c153660046150f6565b6125c9565b348015610c2657600080fd5b50610457600d5481565b348015610c3c57600080fd5b506003546001600160a01b0316610484565b348015610c5a57600080fd5b50610435610c69366004615598565b6125d9565b348015610c7a57600080fd5b506104e9610c89366004615124565b60056020526000908152604090205460ff1681565b348015610caa57600080fd5b50610435610cb93660046150f6565b6125ff565b348015610cca57600080fd5b5061045760105481565b348015610ce057600080fd5b50610457600b5481565b348015610cf657600080fd5b50610435610d05366004615469565b61264c565b348015610d1657600080fd5b50610bcf610d253660046150f6565b612670565b348015610d3657600080fd5b50610435610d45366004615124565b6127e7565b348015610d5657600080fd5b50610bcf610d6536600461525a565b612811565b610435610d783660046155b5565b61284d565b348015610d8957600080fd5b50610d92612be9565b6040516104619190615631565b348015610dab57600080fd5b50610435610dba36600461522e565b612c40565b348015610dcb57600080fd5b50610457610dda3660046150f6565b612f93565b348015610deb57600080fd5b50610435610dfa366004615124565b613135565b348015610e0b57600080fd5b50610435610e1a3660046152f5565b6131a0565b348015610e2b57600080fd5b50610435610e3a366004615124565b613364565b348015610e4b57600080fd5b50610435610e5a3660046150f6565b6133da565b348015610e6b57600080fd5b50610457610e7a366004615748565b6134fb565b348015610e8b57600080fd5b50610435610e9a366004615867565b6135a8565b348015610eab57600080fd5b50610435610eba366004615943565b613805565b610ec7613850565b6109c48161ffff161115610f0d5760405162461bcd60e51b81526020600482015260086024820152670dac2f040646a60f60c31b60448201526064015b60405180910390fd5b600a805461ffff191661ffff92909216919091179055565b60008060008381548110610f3b57610f3b61597e565b90600052602060002090600702016040518060e0016040529081600082018054610f6490615994565b80601f0160208091040260200160405190810160405280929190818152602001828054610f9090615994565b8015610fdd5780601f10610fb257610100808354040283529160200191610fdd565b820191906000526020600020905b815481529060010190602001808311610fc057829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201805480602002602001604051908101604052809291908181526020016000905b82821015611098576000848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b900461ffff168385015260019081015491830191909152908352909201910161103d565b50505091525090915060009050805b8260c00151518110156111405760008360c0015182815181106110cc576110cc61597e565b6020026020010151905060006110e58260000151611875565b92505050816040015160001461111d57670de0b6b3a764000082604001518261110e91906159e4565b6111189190615a03565b61111f565b805b6111299085615a25565b93505050808061113890615a38565b9150506110a7565b509392505050565b60008061115483612f93565b905060005b60008481526017602052604090205481101561122557600084815260176020526040812080548390811061118f5761118f61597e565b906000526020600020906002020160010154905060006017600087815260200190815260200160002083815481106111c9576111c961597e565b9060005260206000209060020201600001548210905080156111fd578184116111f85750600195945050505050565b611210565b8184106112105750600195945050505050565b5050808061121d90615a38565b915050611159565b5060009392505050565b611237613850565b600080828154811061124b5761124b61597e565b90600052602060002090600702019050600181600601805490501161129a5760405162461bcd60e51b8152602060048201526005602482015264092a69288b60db1b6044820152606401610f04565b60005b600682015481101561137d5760006112e28360060183815481106112c3576112c361597e565b60009182526020909120600290910201546001600160a01b0316611875565b92505050806002670de0b6b3a76400006112fc9190615b2d565b8460060184815481106113115761131161597e565b60009182526020909120600290910201546113379190600160a01b900461ffff166159e4565b6113419190615a03565b8360060183815481106113565761135661597e565b6000918252602090912060016002909202010155508061137581615a38565b91505061129d565b505050565b60008060008060008060146000888152602001908152602001600020604051806101a001604052908160008201805480602002602001604051908101604052809291908181526020016000905b8282101561147657600084815260209081902060408051610100810182526003860290920180546001600160a01b03811660a0850190815261ffff600160a01b909204821660c086015260018084015460e0870152908552600290920154808216858701526001600160501b03620100008204811694860194909452600160601b81049091166060850152600160701b9004909116608083015290835290920191016113cf565b505050908252506040805160c080820183526001858101548352600286015460208481019190915260038701548486015260048701546060808601919091526005880154608080870191909152600689015460a0808801919091529288019590955260078801546001600160a01b031695870195909552600887015494860194909452600986015492850192909252600a85015492840192909252600b84015460ff80821615159385019390935261ffff610100918290041660e0850152600c85015490840152600d840154610120840152600e840154610140840152600f84015461016084015260109093015416151561018090910152909150600061157c89612f93565b6101008401519091508082119082106000826115a857838661010001516115a39190615b3c565b6115b8565b6101008601516115b89085615b3c565b90506000866101000151828860a001516115d291906159e4565b6115dc9190615a03565b905060008760c001516115ef57836115f1565b845b6080890151909150811561166f576000620186a0600c548b610100015161161891906159e4565b6116229190615a03565b85101590506000600b548b602001516000015161163f9190615a25565b4210159050818061164d5750805b156116635761165c8584615a25565b9250611668565b600099505b505061168c565b8083111561167f5750600061168c565b6116898382615b3c565b90505b959e959d50909b5099509397509195505050505050565b606060176000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561171e578382906000526020600020906002020160405180604001604052908160008201548152602001600182015481525050815260200190600101906116d8565b505050509050919050565b611731613850565b60008160ff161161176c5760405162461bcd60e51b81526020600482015260056024820152646d696e203160d81b6044820152606401610f04565b6006805460ff191660ff92909216919091179055565b61178a613850565b6102588110156117c65760405162461bcd60e51b81526020600482015260076024820152666d696e2031306d60c81b6044820152606401610f04565b600f55565b6000805b601854811015611849576000601882815481106117ee576117ee61597e565b90600052602060002001549050600061180682611c0b565b90508015611834578361181881615b4f565b60065490955060ff908116908616109050611834575050611849565b5050808061184190615a38565b9150506117cf565b50505050565b611857613850565b600a805460ff909216620100000262ff000019909216919091179055565b6000806000808490506000816001600160a01b03166358303b106040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e29190615b6e565b90506000826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611924573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119489190615b8b565b9050600080846001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561198b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119af9190615bc4565b50505091509150838284600a6119c59190615b2d565b6119d790670de0b6b3a7640000615a03565b6119e190846159e4565b97509750975050505050509193909250565b6002546040516331a9108f60e11b81526004810185905284916001600160a01b031690636352211e90602401602060405180830381865afa158015611a3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a609190615c14565b6001600160a01b0316336001600160a01b031614611a905760405162461bcd60e51b8152600401610f0490615c31565b6118498484846138aa565b600080611aa783612067565b9050600080611ab585612670565b915091506000806000611ac788611382565b5060008c8152601460205260408120600b01549497509295509350909160ff169050611b0f576000898152601460205260409020600c0154611b0a908890615a25565b611b2c565b6000898152601460205260409020600c0154611b2c908890615b3c565b60008a8152601460205260408120600b01549192509060ff16611b525781851015611b57565b818511155b9050600083158015611b72575084611b6f888a615a25565b10155b90508180611b7d5750805b9b9a5050505050505050505050565b601a8181548110611b9c57600080fd5b600091825260209091200154905081565b611bb5613850565b6064611bc5620186a060016159e4565b611bcf9190615a03565b8110611c065760405162461bcd60e51b81526020600482015260066024820152656d617820312560d01b6044820152606401610f04565b601055565b600080611c1783611a9b565b90506000611c2484611148565b90508180611c2f5750805b1561122557611c3f84600161396d565b8115611c7d576040518481527feb7f91469bb290996747407607c0d2bf6b0d11afb8d5ada15dd2269709879eaf9060200160405180910390a1611cb7565b8015611cb7576040518481527fb2f224dd9601ae969b3a64ea0493482e0eead1fa818bc855679c3ad666ea1fef9060200160405180910390a15b5060019392505050565b611cc9613850565b6064611cd9620186a060036159e4565b611ce39190615a03565b8110611d1a5760405162461bcd60e51b81526020600482015260066024820152656d617820332560d01b6044820152606401610f04565b600c55565b6002546040516331a9108f60e11b81526004810184905283916001600160a01b031690636352211e90602401602060405180830381865afa158015611d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8c9190615c14565b6001600160a01b0316336001600160a01b031614611dbc5760405162461bcd60e51b8152600401610f0490615c31565b61137d8383613bdf565b611dce613850565b6064611dde620186a0600a6159e4565b611de89190615a03565b8110611e205760405162461bcd60e51b81526020600482015260076024820152666d61782031302560c81b6044820152606401610f04565b600d55565b6000606060005b601854811015611e9257600060188281548110611e4b57611e4b61597e565b90600052602060002001549050611e6181611a9b565b80611e705750611e7081611148565b15611e7f576001935050611e92565b5080611e8a81615a38565b915050611e2c565b509250929050565b611ea2613850565b611eac6000613c9d565b565b611eb6613850565b6001600160a01b03821660009081526005602052604090205481151560ff909116151503611f0f5760405162461bcd60e51b8152600401610f04906020808252600490820152635345543360e01b604082015260600190565b6001600160a01b03919091166000908152600560205260409020805460ff1916911515919091179055565b6002546040516331a9108f60e11b81526004810184905283916001600160a01b031690636352211e90602401602060405180830381865afa158015611f83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa79190615c14565b6001600160a01b0316336001600160a01b031614611fd75760405162461bcd60e51b8152600401610f0490615c31565b61137d8383613cef565b611fe9613850565b6064611ff9620186a0600a6159e4565b6120039190615a03565b811061203b5760405162461bcd60e51b81526020600482015260076024820152666d61782031302560c81b6044820152606401610f04565b600e55565b612048613850565b6006546120649061010090046001600160a01b03168083613dfc565b50565b6000818152601460205260408120600b810154600c9091015461010090910461ffff16906120969060096159e4565b6120a09190615a03565b92915050565b606060088054806020026020016040519081016040528092919081815260200182805480156120fe57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116120e0575b5050505050905090565b6000818154811061211857600080fd5b906000526020600020906007020160009150905080600001805461213b90615994565b80601f016020809104026020016040519081016040528092919081815260200182805461216790615994565b80156121b45780601f10612189576101008083540402835291602001916121b4565b820191906000526020600020905b81548152906001019060200180831161219757829003601f168201915b5050505050908060010154908060020154908060030154908060040154908060050154905086565b61206481600061396d565b6121ef613850565b8181156121fc5781612264565b6040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa158015612240573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122649190615c5c565b91506000821161227357600080fd5b61137d6122886001546001600160a01b031690565b6001600160a01b0383169084613dfc565b60606000805480602002602001604051908101604052809291908181526020016000905b8282101561243b57838290600052602060002090600702016040518060e00160405290816000820180546122f090615994565b80601f016020809104026020016040519081016040528092919081815260200182805461231c90615994565b80156123695780601f1061233e57610100808354040283529160200191612369565b820191906000526020600020905b81548152906001019060200180831161234c57829003601f168201915b50505050508152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820154815260200160068201805480602002602001604051908101604052809291908181526020016000905b82821015612424576000848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b900461ffff16838501526001908101549183019190915290835290920191016123c9565b5050505081525050815260200190600101906122bd565b50505050905090565b6000818152601460205260408120546060919067ffffffffffffffff81111561246f5761246f615669565b604051908082528060200260200182016040528015612498578160200160208202803683370190505b50905060005b60008481526014602052604090205481101561252f5760008481526014602052604090208054829081106124d4576124d461597e565b600091825260209091206003909102015482516001600160a01b03909116908390839081106125055761250561597e565b6001600160a01b03909216602092830291909101909101528061252781615a38565b91505061249e565b5092915050565b60035460009081906001600160a01b0316612553576000806125c0565b60035460405163a310e73960e01b81526001600160a01b0385811660048301529091169063a310e739906024016040805180830381865afa15801561259c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125c09190615c75565b91509150915091565b60188181548110611b9c57600080fd5b6125e1613850565b60048054911515600160a01b0260ff60a01b19909216919091179055565b612607613850565b620151808111156126475760405162461bcd60e51b815260206004820152600a6024820152696d61782031206461797360b01b6044820152606401610f04565b600b55565b612654613850565b6001600160a01b03909116600090815260136020526040902055565b6002546040516331a9108f60e11b815260048101839052600091829182916001600160a01b031690636352211e90602401602060405180830381865afa1580156126be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e29190615c14565b90506000806126f083612536565b600e546000898152601460205260408120600a01549395509193509091620186a09161271b916159e4565b6127259190615a03565b6010546000898152601460205260408120600a015492935091620186a09161274c916159e4565b6127569190615a03565b600f5460008a815260146020526040812060010154929350916127799042615b3c565b61278390846159e4565b61278d9190615a03565b905084156127d857836127a086856159e4565b6127aa9190615a03565b6127b49084615b3c565b9250836127c186836159e4565b6127cb9190615a03565b6127d59082615b3c565b90505b91989197509095505050505050565b6127ef613850565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6017602052816000526040600020818154811061282d57600080fd5b600091825260209091206002909102018054600190910154909250905082565b600454600160a01b900460ff166128915760405162461bcd60e51b8152602060048201526008602482015267111254d05093115160c21b6044820152606401610f04565b60005487106128cb5760405162461bcd60e51b81526020600482015260066024820152650929cac9288b60d31b6044820152606401610f04565b600a8361ffff16101580156128ea5750600a5461ffff90811690841611155b61291f5760405162461bcd60e51b8152600401610f04906020808252600490820152634c45563160e01b604082015260600190565b61292a876000613e5f565b6129605760405162461bcd60e51b8152602060048201526007602482015266494e444f4f423160c81b6044820152606401610f04565b6001600160a01b038816158061298857506006546001600160a01b0389811661010090920416145b806129ab57506001600160a01b03881660009081526007602052604090205460ff165b6129e35760405162461bcd60e51b8152602060048201526009602482015268504f53544f4b454e3160b81b6044820152606401610f04565b6002546040516335313c2160e11b81523360048201526000916001600160a01b031690636a627842906024016020604051808303816000875af1158015612a2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a529190615c5c565b9050600080612a67338c898961ffff16613f05565b915091506000612a778b85614137565b90506000612a848c610f25565b9050612a928b828c8a614342565b600085815260156020526040902080546001600160a01b031916331790554260018301556002820184905560098201839055600a612ad461ffff8a16856159e4565b612ade9190615a03565b600a830155600b8201805462ffffff191688151562ffff0019161761010061ffff8b1602179055600c82018190556007820180546001600160a01b0319166001600160a01b038f16179055601880546000878152601960205260408120829055600182018355919091527fb13d2d76d1f4b7be834882e410b3e3a8afaf69f83600ae24db354391d2378d2e01859055612b7b8583600a0154614400565b8515612b8b57612b8b8587613cef565b60408051828152602081018590528815158183015261ffff8a1660608201529051339187917f7851a428332e40237ac34a5efd508d9bbff0fb057da46bf99e1bd1b5c4adf6719181900360800190a350505050505050505050505050565b6060601a8054806020026020016040519081016040528092919081815260200182805480156120fe57602002820191906000526020600020905b815481526020019060010190808311612c23575050505050905090565b3360009081526005602052604090205460ff16612c8f5760405162461bcd60e51b815260206004820152600d60248201526c6f6e6c7920736574746c65727360981b6044820152606401610f04565b6000838152601460205260409020601081015460ff1615612cdb5760405162461bcd60e51b8152600401610f04906020808252600490820152635345543160e01b604082015260600190565b6000816008015411612d185760405162461bcd60e51b8152600401610f049060208082526004908201526329a2aa1960e11b604082015260600190565b60108101805460ff19166001179055600581018390556006810182905560078101546040805163313ce56760e01b815290516000926001600160a01b03169163313ce5679160048281019260209291908290030181865afa158015612d81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da59190615b8b565b612db090600a615b2d565b8385600660019054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e299190615b8b565b612e3490600a615b2d565b8560080154612e4391906159e4565b612e4d91906159e4565b612e579190615a03565b612e619190615a03565b600086815260166020526040902054600654919250612e929161010090046001600160a01b03908116911683613dfc565b6000858152601b6020526040812054601a8054919291612eb490600190615b3c565b81548110612ec457612ec461597e565b6000918252602080832090910154898352601b9091526040808320839055818352909120839055601a8054919250829184908110612f0457612f0461597e565b600091825260209091200155601a805480612f2157612f21615c99565b600190038181906000526020600020016000905590557f4c246f6c8d41233463bbb11c80907ea3f18c0b7c101910bfa5a599f65cacab4f87848888604051612f82949392919093845260208401929092526040830152606082015260800190565b60405180910390a150505050505050565b600081815260146020526040812054819067ffffffffffffffff811115612fbc57612fbc615669565b604051908082528060200260200182016040528015612fe5578160200160208202803683370190505b506000848152601460205260408120549192509067ffffffffffffffff81111561301157613011615669565b60405190808252806020026020018201604052801561303a578160200160208202803683370190505b50905060005b6000858152601460205260409020548110156131225760008581526014602052604090208054829081106130765761307661597e565b600091825260209091206003909102015483516001600160a01b03909116908490839081106130a7576130a761597e565b6001600160a01b0390921660209283029190910182015260008681526014909152604090208054829081106130de576130de61597e565b9060005260206000209060030201600001600101548282815181106131055761310561597e565b60209081029190910101528061311a81615a38565b915050613040565b5061312d82826134fb565b949350505050565b61313d613850565b601854156131785760405162461bcd60e51b81526020600482015260086024820152671350525390d3d31360c21b6044820152606401610f04565b600680546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6131a8613850565b6001600160a01b03821660009081526007602052604090205481151560ff9091161515036132075760405162461bcd60e51b815260206004820152600c60248201526b6368616e676520737461746560a01b6044820152606401610f04565b6001600160a01b0382166000908152600760205260409020805460ff1916821580159190911790915561329457600880546001600160a01b0384166000818152600960205260408120839055600183018455929092527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b03191690911790555050565b6001600160a01b03821660009081526009602052604081208054919055600880546132c190600190615b3c565b815481106132d1576132d161597e565b600091825260209091200154600880546001600160a01b0390921691839081106132fd576132fd61597e565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600880548061333c5761333c615c99565b600082815260209020810160001990810180546001600160a01b0319169055019055505b5050565b61336c613850565b6001600160a01b0381166133d15760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610f04565b61206481613c9d565b6133e2613850565b600080546133f290600190615b3c565b815481106134025761340261597e565b9060005260206000209060070201600082815481106134235761342361597e565b600091825260209091206007909102018061343e8382615cfd565b5060018201548160010155600282015481600201556003820154816003015560048201548160040155600582015481600501556006820181600601908054613487929190614f9b565b50905050600080548061349c5761349c615c99565b600082815260208120600019909201916007830201906134bc8282615037565b600182016000905560028201600090556003820160009055600482016000905560058201600090556006820160006134f49190615071565b5050905550565b6000815183511461350b57600080fd5b6000805b845181101561114057600061353c86838151811061352f5761352f61597e565b6020026020010151611875565b92505050855160011461358657670de0b6b3a76400008583815181106135645761356461597e565b60200260200101518261357791906159e4565b6135819190615a03565b613588565b805b6135929084615a25565b92505080806135a090615a38565b91505061350f565b6135b0613850565b600082511180156135c2575080518251145b6135f95760405162461bcd60e51b815260206004820152600860248201526739b0b6b2903632b760c11b6044820152606401610f04565b600080546001810182559080526007027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56301806136368582615dda565b5060005b83518110156137fe5760008482815181106136575761365761597e565b60200260200101519050600061366c82611875565b92505050600081116136b05760405162461bcd60e51b815260206004820152600d60248201526c696e76616c69642070726f787960981b6044820152606401610f04565b85516001146136d8578483815181106136cb576136cb61597e565b60200260200101516136db565b60005b61ffff168460010160008282546136f29190615a25565b92505081905550836006016040518060600160405280846001600160a01b031681526020018786815181106137295761372961597e565b602002602001015161ffff168152602001885160011461378e57836137576002670de0b6b3a7640000615b2d565b8988815181106137695761376961597e565b602002602001015161ffff1661377f91906159e4565b6137899190615a03565b613791565b60005b90528154600181810184556000938452602093849020835160029093020180549484015161ffff16600160a01b026001600160b01b03199095166001600160a01b0390931692909217939093178155604090910151910155508190506137f681615a38565b91505061363a565b5050505050565b61380d613850565b60008086815481106138215761382161597e565b600091825260209091206007909102016002810195909555506003840192909255600483015560059091015550565b6001546001600160a01b03163314611eac5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f04565b600081116138e05760405162461bcd60e51b81526020600482015260036024820152620544f360ec1b6044820152606401610f04565b60008381526017602052604081208054849081106139005761390061597e565b906000526020600020906002020190506000816000015482600101541090508061392d5781548311613932565b815483105b6139645760405162461bcd60e51b8152602060048201526003602482015262544f3360e81b6044820152606401610f04565b50600101555050565b6002546040516331a9108f60e11b8152600481018490526000916001600160a01b031690636352211e90602401602060405180830381865afa1580156139b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139db9190615c14565b905081806139f15750336001600160a01b038216145b613a255760405162461bcd60e51b81526020600482015260056024820152644f574e4c5160d81b6044820152606401610f04565b60025460405163c3738f3f60e01b8152600481018590526001600160a01b039091169063c3738f3f90602401602060405180830381865afa158015613a6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a929190615e92565b613ac75760405162461bcd60e51b8152602060048201526006602482015265434c4f53453160d01b6044820152606401610f04565b613ad183826145e9565b613ada836146be565b613ae383614768565b613aec83614832565b600254604051630852cd8d60e31b8152600481018590526001600160a01b03909116906342966c6890602401600060405180830381600087803b158015613b3257600080fd5b505af1158015613b46573d6000803e3d6000fd5b505050600084815260166020908152604080832080546001600160a01b0319166001600160a01b0387169081179091556014835292819020600c810154600d820154600e830154600f9093015484519283529482015291820152606081019190915290915084907fad61fdefcf969920b58ee3fc753c769d85f23f36b446cf737c0c5e7dcf840a6e9060800160405180910390a3505050565b60008281526017602052604090208054613bfb90600190615b3c565b81548110613c0b57613c0b61597e565b9060005260206000209060020201601760008481526020019081526020016000208281548110613c3d57613c3d61597e565b6000918252602080832084546002909302019182556001938401549390910192909255838152601790915260409020805480613c7b57613c7b615c99565b6000828152602081206002600019909301928302018181556001015590555050565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008111613d255760405162461bcd60e51b81526020600482015260036024820152620544f360ec1b6044820152606401610f04565b600a546000838152601760205260409020546201000090910460ff1611613d745760405162461bcd60e51b8152602060048201526003602482015262544f3160e81b6044820152606401610f04565b6000613d7f83612f93565b9050818103613db65760405162461bcd60e51b81526020600482015260036024820152622a279960e91b6044820152606401610f04565b6000928352601760209081526040808520815180830190925292815280820193845282546001818101855593865291909420935160029091029093019283559051910155565b6040516001600160a01b03831660248201526044810182905261137d90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526148dd565b6000613efe8260008581548110613e7857613e7861597e565b90600052602060002090600702016002015460008681548110613e9d57613e9d61597e565b90600052602060002090600702016003015460008781548110613ec257613ec261597e565b90600052602060002090600702016004015460008881548110613ee757613ee761597e565b9060005260206000209060070201600501546149af565b9392505050565b60008080806001600160a01b038716613f715760003411613f505760405162461bcd60e51b8152602060048201526005602482015264434f4c4c3360d81b6044820152606401610f04565b349550613f5e888787614b1b565b9150613f6a8287615b3c565b905061412a565b6040516370a0823160e01b81526001600160a01b038981166004830152889188918316906370a0823190602401602060405180830381865afa158015613fbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fdf9190615c5c565b10156140165760405162461bcd60e51b8152600401610f049060208082526004908201526342414c3160e01b604082015260600190565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa15801561405d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140819190615c5c565b90506140986001600160a01b0383168b308b614b9b565b6040516370a0823160e01b815230600482015281906001600160a01b038416906370a0823190602401602060405180830381865afa1580156140de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141029190615c5c565b61410c9190615b3c565b97506141198a8989614b1b565b93506141258489615b3c565b925050505b9097909650945050505050565b6000818152601460205260408120815b6000858154811061415a5761415a61597e565b906000526020600020906007020160060180549050811015611140576000806141b16000888154811061418f5761418f61597e565b906000526020600020906007020160060184815481106112c3576112c361597e565b5091509150836000016040518060a0016040528060008a815481106141d8576141d861597e565b906000526020600020906007020160060186815481106141fa576141fa61597e565b600091825260208083206040805160608082018352600295860290930180546001600160a01b03808216845261ffff600160a01b9283900481168589015260019384015485870152938a529c8316898701526001600160501b039b8c168985015288850188905260809889018890528a548083018c559a885296859020895180516003909c0290910180548288015185169099026001600160b01b03199099169b909d169a909a17969096178b5597810151948a019490945590850151979091018054928501519185015194909301518616600160701b0269ffffffffffffffffffff60701b19948616600160601b02949094166bffffffffffffffffffffffff60601b199190961662010000026bffffffffffffffffffffffff1990921696909416959095179490941791909116919091171790558061433a81615a38565b915050614147565b600081801561435057508484115b156143665761435f8585615b3c565b9050614385565b8115801561437357508385115b15614385576143828486615b3c565b90505b80156137fe576103e86143a0670de0b6b3a7640000856159e4565b6143aa9190615a03565b856143bd670de0b6b3a7640000846159e4565b6143c79190615a03565b11156137fe5760405162461bcd60e51b8152602060048201526008602482015267534c49505041474560c01b6044820152606401610f04565b6000828152601460205260409020600b015460ff161561445c576000828152601460209081526040808320600701546001600160a01b03168352601190915281208054839290614451908490615a25565b909155506144999050565b6000828152601460209081526040808320600701546001600160a01b03168352601290915281208054839290614493908490615a25565b90915550505b6000828152601460209081526040808320600701546001600160a01b03168352601390915290205415613360576000828152601460209081526040808320600701546001600160a01b03168352601282528083205460119092528220541161453b576000838152601460209081526040808320600701546001600160a01b0316835260118252808320546012909252909120546145369190615b3c565b614576565b6000838152601460209081526040808320600701546001600160a01b0316835260128252808320546011909252909120546145769190615b3c565b6000848152601460209081526040808320600701546001600160a01b03168352601390915290205490915081111561137d5760405162461bcd60e51b81526020600482015260166024820152751b585e0818dbdb1b185d195c985b081c995858da195960521b6044820152606401610f04565b6000828152601460205260408120908061460285612670565b909250905060006146138284615a25565b905060008060008060006146268b611382565b94509450945094509450838611614646576146418685615b3c565b614649565b60005b93506146568b8b86614bd3565b4260038a015560048901869055600d89018590558180156146745750805b61467f576000614681565b825b600e8a0155816146a6578860090154831161469c57826146a9565b88600901546146a9565b60005b89600f01819055505050505050505050505050565b600081815260196020526040812054601880549192916146e090600190615b3c565b815481106146f0576146f061597e565b600091825260208083209091015485835260199091526040808320839055818352909120839055601880549192508291849081106147305761473061597e565b600091825260209091200155601880548061474d5761474d615c99565b60019003818190600052602060002001600090559055505050565b60005b6000828152601460205260409020548110156133605760008281526014602052604081208054839081106147a1576147a161597e565b600091825260208220600390910201805490925081906147c9906001600160a01b0316611875565b50600290940180546001600160501b03909516600160701b0269ffffffffffffffffffff60701b1961ffff909316600160601b02929092166bffffffffffffffffffffffff60601b1990951694909417179092555081905061482a81615a38565b91505061476b565b6000818152601460205260409020600b015460ff1615614896576000818152601460209081526040808320600a8101546007909101546001600160a01b031684526011909252822080549192909161488b908490615b3c565b909155506120649050565b6000818152601460209081526040808320600a8101546007909101546001600160a01b03168452601290925282208054919290916148d5908490615b3c565b909155505050565b6000614932826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614e879092919063ffffffff16565b80519091501561137d57808060200190518101906149509190615e92565b61137d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610f04565b600085156149bd57856149bf565b425b9550600185101580156149d3575060018410155b15614a68576004805460405163045f145760e31b81529182018890526000916001600160a01b03909116906322f8a2b890602401602060405180830381865afa158015614a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a489190615c5c565b905085811080614a5757508481115b15614a66576000915050614b12565b505b600183101580614a79575060018210155b15614b0e5760048054604051631f11cf0d60e11b81529182018890526000916001600160a01b0390911690633e239e1a90602401602060405180830381865afa158015614aca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614aee9190615c5c565b905083811080614afd57508281115b15614b0c576000915050614b12565b505b5060015b95945050505050565b600080600a614b2a84866159e4565b614b349190615a03565b90506000620186a0600d5483614b4a91906159e4565b614b549190615a03565b9050600080614b6288612536565b90925090508115614b8f5780614b7883856159e4565b614b829190615a03565b614b8c9084615b3c565b92505b50909695505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526118499085906323b872dd60e01b90608401613e28565b60008381526014602052604090208115614e725760065460078201546001600160a01b036101009092048216911603614c335760108101805460ff191660011790556007810154614c2e906001600160a01b03168484613dfc565b611849565b8060090154821115614d9b5760078101546001600160a01b0316614cf457600981015460405147916001600160a01b03861691600081818185875af1925050503d8060008114614c9f576040519150601f19603f3d011682016040523d82523d6000602084013e614ca4565b606091505b5050506009820154614cb69082615b3c565b471015614cee5760405162461bcd60e51b8152600401610f04906020808252600490820152634e41543160e01b604082015260600190565b50614d15565b60098101546007820154614d15916001600160a01b03909116908590613dfc565b6009810154614d249083615b3c565b6008820155601a80546000868152601b60205260408082208390556001830184559281527f057c384a7d1c54f3a1b2e5e67b2617b8224fdfd1ea7234eea573a6ff665ff63e909101869055905185917f1cf3a4d81180ed8c843ad38f7adadb6357459df6a134d14614cf7ca32dbee42191a2611849565b60108101805460ff1916600117905560078101546001600160a01b0316614e595760405147906001600160a01b038516908490600081818185875af1925050503d8060008114614e07576040519150601f19603f3d011682016040523d82523d6000602084013e614e0c565b606091505b5050508281614e1b9190615b3c565b471015614e535760405162461bcd60e51b8152600401610f04906020808252600490820152634e41543160e01b604082015260600190565b50611849565b6007810154614c2e906001600160a01b03168484613dfc565b60108101805460ff1916600117905550505050565b606061312d8484600085856001600160a01b0385163b614ee95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610f04565b600080866001600160a01b03168587604051614f059190615eaf565b60006040518083038185875af1925050503d8060008114614f42576040519150601f19603f3d011682016040523d82523d6000602084013e614f47565b606091505b5091509150614f57828286614f62565b979650505050505050565b60608315614f71575081613efe565b825115614f815782518084602001fd5b8160405162461bcd60e51b8152600401610f049190615ecb565b8280548282559060005260206000209060020281019282156150275760005260206000209160020282015b8281111561502757825482546001600160a01b039091166001600160a01b031982168117845584546001600160b01b031990921617600160a01b9182900461ffff169091021782556001808401549083015560029283019290910190614fc6565b5061503392915061508e565b5090565b50805461504390615994565b6000825580601f10615053575050565b601f01602090049060005260206000209081019061206491906150b4565b508054600082556002029060005260206000209081019061206491905b5b808211156150335780546001600160b01b03191681556000600182015560020161508f565b5b8082111561503357600081556001016150b5565b61ffff8116811461206457600080fd5b6000602082840312156150eb57600080fd5b8135613efe816150c9565b60006020828403121561510857600080fd5b5035919050565b6001600160a01b038116811461206457600080fd5b60006020828403121561513657600080fd5b8135613efe8161510f565b602080825282518282018190526000919060409081850190868401855b828110156151835781518051855286015186850152928401929085019060010161515e565b5091979650505050505050565b60ff8116811461206457600080fd5b6000602082840312156151b157600080fd5b8135613efe81615190565b600080602083850312156151cf57600080fd5b823567ffffffffffffffff808211156151e757600080fd5b818501915085601f8301126151fb57600080fd5b81358181111561520a57600080fd5b86602082850101111561521c57600080fd5b60209290920196919550909350505050565b60008060006060848603121561524357600080fd5b505081359360208301359350604090920135919050565b6000806040838503121561526d57600080fd5b50508035926020909101359150565b60005b8381101561529757818101518382015260200161527f565b50506000910152565b600081518084526152b881602086016020860161527c565b601f01601f19169290920160200192915050565b821515815260406020820152600061312d60408301846152a0565b801515811461206457600080fd5b6000806040838503121561530857600080fd5b82356153138161510f565b91506020830135615323816152e7565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b81811015614b8f5783516001600160a01b03168352928401929184019160010161534a565b60c08152600061538260c08301896152a0565b60208301979097525060408101949094526060840192909252608083015260a090910152919050565b6000610220820190508d51825260208e0151602083015260408e0151604083015260608e0151606083015260808e0151608083015260a08e015160a08301526153ff60c083018e6001600160a01b03169052565b8b60e08301528a6101008301528961012083015261542261014083018a15159052565b61ffff881661016083015286610180830152856101a0830152846101c0830152836101e083015261545861020083018415159052565b9d9c50505050505050505050505050565b6000806040838503121561547c57600080fd5b82356154878161510f565b946020939093013593505050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b8481101561558957603f198a8503018652825160e081518187526154e3828801826152a0565b838c0151888d01528a8401518b890152606080850151818a0152608080860151908a015260a080860151908a015260c094850151898303958a01959095528451808352948d0194879450909250908c01905b8084101561557357845180516001600160a01b031683528d81015161ffff168e8401528c01518c830152938c01936001939093019290820190615535565b50988b01989650505092880192506001016154bd565b50919998505050505050505050565b6000602082840312156155aa57600080fd5b8135613efe816152e7565b600080600080600080600080610100898b0312156155d257600080fd5b88356155dd8161510f565b97506020890135965060408901359550606089013594506080890135935060a0890135615609816150c9565b925060c0890135615619816152e7565b8092505060e089013590509295985092959890939650565b6020808252825182820181905260009190848201906040850190845b81811015614b8f5783518352928401929184019160010161564d565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff811182821017156156a8576156a8615669565b604052919050565b600067ffffffffffffffff8211156156ca576156ca615669565b5060051b60200190565b600082601f8301126156e557600080fd5b813560206156fa6156f5836156b0565b61567f565b82815260059290921b8401810191818101908684111561571957600080fd5b8286015b8481101561573d5780356157308161510f565b835291830191830161571d565b509695505050505050565b6000806040838503121561575b57600080fd5b823567ffffffffffffffff8082111561577357600080fd5b61577f868387016156d4565b935060209150818501358181111561579657600080fd5b85019050601f810186136157a957600080fd5b80356157b76156f5826156b0565b81815260059190911b820183019083810190888311156157d657600080fd5b928401925b828410156157f4578335825292840192908401906157db565b80955050505050509250929050565b600082601f83011261581457600080fd5b813560206158246156f5836156b0565b82815260059290921b8401810191818101908684111561584357600080fd5b8286015b8481101561573d57803561585a816150c9565b8352918301918301615847565b60008060006060848603121561587c57600080fd5b833567ffffffffffffffff8082111561589457600080fd5b818601915086601f8301126158a857600080fd5b81356020828211156158bc576158bc615669565b6158ce601f8301601f1916820161567f565b82815289828487010111156158e257600080fd5b8282860183830137600092810182019290925290955086013591508082111561590a57600080fd5b615916878388016156d4565b9350604086013591508082111561592c57600080fd5b5061593986828701615803565b9150509250925092565b600080600080600060a0868803121561595b57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806159a857607f821691505b6020821081036159c857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b60008160001904831182151516156159fe576159fe6159ce565b500290565b600082615a2057634e487b7160e01b600052601260045260246000fd5b500490565b808201808211156120a0576120a06159ce565b600060018201615a4a57615a4a6159ce565b5060010190565b600181815b80851115611e92578160001904821115615a7257615a726159ce565b80851615615a7f57918102915b93841c9390800290615a56565b600082615a9b575060016120a0565b81615aa8575060006120a0565b8160018114615abe5760028114615ac857615ae4565b60019150506120a0565b60ff841115615ad957615ad96159ce565b50506001821b6120a0565b5060208310610133831016604e8410600b8410161715615b07575081810a6120a0565b615b118383615a51565b8060001904821115615b2557615b256159ce565b029392505050565b6000613efe60ff841683615a8c565b818103818111156120a0576120a06159ce565b600060ff821660ff8103615b6557615b656159ce565b60010192915050565b600060208284031215615b8057600080fd5b8151613efe816150c9565b600060208284031215615b9d57600080fd5b8151613efe81615190565b80516001600160501b0381168114615bbf57600080fd5b919050565b600080600080600060a08688031215615bdc57600080fd5b615be586615ba8565b9450602086015193506040860151925060608601519150615c0860808701615ba8565b90509295509295909350565b600060208284031215615c2657600080fd5b8151613efe8161510f565b60208082526011908201527036bab9ba1037bbb7103837b9b4ba34b7b760791b604082015260600190565b600060208284031215615c6e57600080fd5b5051919050565b60008060408385031215615c8857600080fd5b505080516020909101519092909150565b634e487b7160e01b600052603160045260246000fd5b601f82111561137d57600081815260208120601f850160051c81016020861015615cd65750805b601f850160051c820191505b81811015615cf557828155600101615ce2565b505050505050565b818103615d08575050565b615d128254615994565b67ffffffffffffffff811115615d2a57615d2a615669565b615d3e81615d388454615994565b84615caf565b6000601f821160018114615d725760008315615d5a5750848201545b600019600385901b1c1916600184901b1784556137fe565b600085815260209020601f19841690600086815260209020845b83811015615dac5782860154825560019586019590910190602001615d8c565b5085831015615dca5781850154600019600388901b60f8161c191681555b5050505050600190811b01905550565b815167ffffffffffffffff811115615df457615df4615669565b615e0281615d388454615994565b602080601f831160018114615e375760008415615e1f5750858301515b600019600386901b1c1916600185901b178555615cf5565b600085815260208120601f198616915b82811015615e6657888601518255948401946001909101908401615e47565b5085821015615dca57939096015160001960f8600387901b161c19169092555050600190811b01905550565b600060208284031215615ea457600080fd5b8151613efe816152e7565b60008251615ec181846020870161527c565b9190910192915050565b602081526000613efe60208301846152a056fea164736f6c6343000810000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003768747470733a2f2f6170692e7969656c64696669636174696f6e2e636f6d2f70667964662f617262697472756d2f6d657461646174612f000000000000000000
-----Decoded View---------------
Arg [0] : _tokenURI (string): https://api.yieldification.com/pfydf/arbitrum/metadata/
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000037
Arg [2] : 68747470733a2f2f6170692e7969656c64696669636174696f6e2e636f6d2f70
Arg [3] : 667964662f617262697472756d2f6d657461646174612f000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$32.03
Net Worth in ETH
0.01119
Token Allocations
ETH
71.55%
YDF
27.83%
AMX
0.62%
Multichain Portfolio | 35 Chains
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.